汇编语言程序设计--03--16位汇编实模式环境搭建


到了这个点了,看来很有必要搞个中文写作ai, 不然老是修修改改的,这也不是一个事。

汇编从实模式到保护模式,linux0.11系统也是如此,而它的实现语言从as86实模式汇编到gnu汇编再到c语言,其中c跟gnu汇编是其核心实现语言。那么为了更好的理解linux0.11或者说手动去改写一些东西,那么as86是必须要深入了解的。
可as86这种实模式下的汇编,其编译运行环境也是非常有讲究的,它并不像学校里边那种在dos模拟器运行的masm汇编,下载个模拟器就可以直接上手了。
当然模拟器这类思路是可以的,不过16位实模式汇编就需要手动去做。个人实力不够,搭建不了类似dos模拟器。这里的思路,我借用linux0.11源码tools/build.c文件,接着借助makefile功能,在makefile文件里边实现build.c 将as86 ld86编译链接的执行代码写入一个名为RunImage的文件,最后由bochs模拟器去运行makefile模块生成的代码。这样就实现了16位汇编编译运行。同样的思路,我也可以采用bochs的gdb来调试16位汇编代码。

目前我也不是学的很深,暂时就编译运行环境就可以了。我就那几句代码,要啥自行车。

我去看了linux5.15启动代码,额… as86似乎没必要学,nasm也没必要,gnu汇编就可以解决,可路得一步步走,先把linux0.11搞明白,再去搞那些。人生的路很长,没必要过度努力混个重症住院。

复制相关文件

在这里插入图片描述

bochs是虚拟机,一般虚拟机有磁盘。一台裸机的首次启动逻辑,从启动盘再到磁盘。这里的build.c就是将生成的汇编编译链接后的执行文件,最后以某种格式写入到RunImage。
下边是bochs运行配置文件,软盘为启动盘,其目录为$OSLAB_PATH/src/RunImage,那么build.c就是为了生成
这么一个文件。

romimage: file=$OSLAB_PATH/bochs/BIOS-bochs-latest
megs: 16
vgaromimage: file=$OSLAB_PATH/bochs/vgabios.bin
floppya: 1_44="$OSLAB_PATH/src/RunImage", status=inserted
ata0-master: type=disk, path="$OSLAB_PATH/hdc-0.11.img", mode=flat, cylinders=204, heads=16, spt=38
boot: a
log: $OSLAB_PATH/bochsout.txt
#parport1: enable=0
#vga_update_interval: 300000
#keyboard_serial_delay: 200
#keyboard_paste_delay: 100000
#floppy_command_delay: 50000
cpu: count=1, ips=4000000
mouse: enabled=0
private_colormap: enabled=0
fullscreen: enabled=0
screenmode: name="sample"
#i440fxsupport: enabled=0
#display_library: sdl

编写运行相关代码

demo.S

.globl begtext, begdata, begbss, endtext, enddata, endbss
.text
begtext:
.data
begdata:
.bss
begbss:
.text

BOOTSEG = 0x07C0

entry _start
_start:
	mov	ax,#BOOTSEG   !将ds 段寄存器置为0×7C0
	mov	ds,ax
	mov es,ax
	mov	ah,#0x03		! read cursor pos
	xor	bh,bh			! 首先读光标位置。返回光标位置值在dx中
	int	0x10			! dh - 行(0--24); dl - 列(0--79),移动光标

	mov	cx,#36			! 共显示36个字符
	mov	bx,#0x0007		! page 0, attribute 7 (normal)
	mov	bp,#msg		! es:bp 指向要显示的字符串
	mov	ax,#0x1301		! write string, move cursor
	int	0x10			! 写字符串并移动光标到串结尾处

loop0:          ! 屏幕暂停到这里
    jmp loop0
msg:
   .ascii "Loading system..."
   .byte 13,10   ! 换行
	 
   .org 510
   .word 0xAA55

.text
endtext:
.data
enddata:
.bss
endbss:

makefile编译文件

# 定义RAM盘,若定义了则需要指定参数DRAMDISK块大小
RAMDISK =  #-DRAMDISK=512

# 8086汇编语言的汇编器与链接器
# -0表示生成8086目标程序
AS86	=as86 -0 -a
LD86	=ld86 -0

# GNU编译器与链接器
AS	=as
LD	=ld

# GNU链接器LD的参数
# -m elf_i386表示以elf格式输出i386的32位代码
# -Ttext 0表示代码在0处加载/对齐
# -e startup_32表示指定startup_32为入口点
LDFLAGS	=-m elf_i386 -Ttext 0 -e startup_32

# 指定gcc-3.4编译时使用-i386的指令集
CC	=gcc-3.4 -march=i386 $(RAMDISK)

# -m32表示在64位编译器上生成32位的代码
# -g表示生成调试文件(用于GDB调试)
# -Wall表示打印警告信息
# -O2表示使用二级优化
# -fomit-frame-pointer表示对无需帧指针的函数不把帧指针保留在寄存器中
CFLAGS	=-m32 -g -Wall -O2 -fomit-frame-pointer 

# 指定头文件的搜索目录为当前目录下的include(即不使用系统/usr/include目录下的头文件)
CPP	=cpp -nostdinc -Iinclude

# 指定在build程序创建内核映像文件(Image)时所使用的默认根文件系统所在的设备(未指定时,使用默认值/dev/hd6)
ROOT_DEV= #FLOPPY 


# 定义3条了make的隐式规则
# 当源文件是.c文件,目标文件是.s文件,则使用第1条规则
# 当源文件是.s文件,目标文件是.o文件,则使用第2条规则
# 当源文件是.c文件,目标文件是.o文件,则使用第3条规则
.c.s:
	$(CC) $(CFLAGS) \
	-nostdinc -Iinclude -S -o $*.s $<
.s.o:
	$(AS)  -o $*.o $<
.c.o:
	$(CC) $(CFLAGS) \
	-nostdinc -Iinclude -c -o $*.o $<

# all为当前MAkefile文件的最终目标,其依赖于Image(make基本知识)
all:	RunImage

# 用于生成Image映像文件,其依赖于1个目标文件
RunImage: demo tools/build
	tools/build demo $(ROOT_DEV) > RunImage
	sync

# 编译链接build.c程序
tools/build: tools/build.c
	gcc $(CFLAGS) -o tools/build tools/build.c

# 使用86的汇编器和链接器编译生成setup文件
demo: demo.S
	$(AS86) -o demo.o demo.S
	$(LD86) -s -o demo demo.o

# 用于清除make执行过程中生成的文件
clean:
	rm -f RunImage demo demo.o tools/build

run脚本

#!/bin/sh
export OSLAB_PATH=$(dirname `which $0`)

bochs -q -f $OSLAB_PATH/bochs/bochsrc.bxrc

运行结果

在这里插入图片描述

利用codeRunner实现一键编译运行

code Runner 的josn配置setting.json( “code-runner.executorMapByFileExtension”)

               ".S": "cd /usr/linux-os/assembly/as86/src && make clean && cp $dir$fileName /usr/linux-os/assembly/as86/src/demo.S && make all && make cleanMiddle && cd /usr/linux-os/assembly/as86 && ./run",

上边不够好,借助code runner预定义变量,再改动下:
        ".S": "cd $workspaceRoot/assembly/as86/src && make clean && cp $fullFileName $workspaceRoot/assembly/as86/src/demo.S && make all && make cleanMiddle && cd $workspaceRoot/assembly/as86 && ./run",


code runner vscode图形界面配置:

需要勾选上。

Code-runner: Run In Terminal
√ Whether to run code in Integrated Terminal.

修改makefile

# 定义RAM盘,若定义了则需要指定参数DRAMDISK块大小
RAMDISK =  #-DRAMDISK=512

# 8086汇编语言的汇编器与链接器
# -0表示生成8086目标程序
AS86	=as86 -0 -a
LD86	=ld86 -0

# GNU编译器与链接器
AS	=as
LD	=ld

# GNU链接器LD的参数
# -m elf_i386表示以elf格式输出i386的32位代码
# -Ttext 0表示代码在0处加载/对齐
# -e startup_32表示指定startup_32为入口点
LDFLAGS	=-m elf_i386 -Ttext 0 -e startup_32

# 指定gcc-3.4编译时使用-i386的指令集
CC	=gcc-3.4 -march=i386 $(RAMDISK)

# -m32表示在64位编译器上生成32位的代码
# -g表示生成调试文件(用于GDB调试)
# -Wall表示打印警告信息
# -O2表示使用二级优化
# -fomit-frame-pointer表示对无需帧指针的函数不把帧指针保留在寄存器中
CFLAGS	=-m32 -g -Wall -O2 -fomit-frame-pointer 

# 指定头文件的搜索目录为当前目录下的include(即不使用系统/usr/include目录下的头文件)
CPP	=cpp -nostdinc -Iinclude

# 指定在build程序创建内核映像文件(Image)时所使用的默认根文件系统所在的设备(未指定时,使用默认值/dev/hd6)
ROOT_DEV= #FLOPPY 


# 定义3条了make的隐式规则
# 当源文件是.c文件,目标文件是.s文件,则使用第1条规则
# 当源文件是.s文件,目标文件是.o文件,则使用第2条规则
# 当源文件是.c文件,目标文件是.o文件,则使用第3条规则
.c.s:
	$(CC) $(CFLAGS) \
	-nostdinc -Iinclude -S -o $*.s $<
.s.o:
	$(AS)  -o $*.o $<
.c.o:
	$(CC) $(CFLAGS) \
	-nostdinc -Iinclude -c -o $*.o $<

# all为当前MAkefile文件的最终目标,其依赖于Image(make基本知识)
all:	RunImage

# 用于生成Image映像文件,其依赖于1个目标文件
RunImage: demo tools/build
	tools/build demo $(ROOT_DEV) > RunImage
	sync

# 编译链接build.c程序
tools/build: tools/build.c
	gcc $(CFLAGS) -o tools/build tools/build.c

# 使用86的汇编器和链接器编译生成setup文件
demo: demo.S
	$(AS86) -o demo.o demo.S
	$(LD86) -s -o demo demo.o

# 用于清除make执行过程中生成的所有文件
clean:
	rm -f RunImage demo demo.o tools/build

# 用于清除make执行过程中生成的中间文件
cleanMiddle:
	rm -f demo.S demo demo.o tools/build

运行结果

在这里插入图片描述

vscode预定义全局变量

以官网文档为准 : https://code.visualstudio.com/docs/editor/variables-reference

${userHome} - 用户主文件夹的路径
${workspaceFolder} - 在 VS Code 中打开的文件夹的路径
${workspaceFolderBasename} - 在 VS Code 中打开的文件夹的名称,不带任何斜杠 (/)
${file} - 当前打开的文件
${fileWorkspaceFolder} - 当前打开的文件的工作区文件夹
${relativeFile} - 当前打开的文件,相对于workspaceFolder
${relativeFileDirname} - 当前打开的文件的目录名称相对于workspaceFolder
${fileBasename} - 当前打开的文件的基名称
${fileBasenameNoExtension} - 当前打开的文件的基本名称,没有文件扩展名
${fileExtname} - 当前打开的文件的扩展名
${fileDirname} - 当前打开的文件的文件夹路径
${fileDirnameBasename} - 当前打开的文件的文件夹名称
${cwd} - VS Code 启动时任务运行程序的当前工作目录
${lineNumber} - 活动文件中当前选定的行号
${selectedText} - 活动文件中当前选定的文本
${execPath} - 正在运行的 VS Code 可执行文件的路径
${defaultBuildTask} - 默认构建任务的名称
${pathSeparator} - 操作系统用来分隔文件路径中组件的字符
${/}- ${pathSeparator} 的简写

Code Runner预定义变量

$workspaceRoot   vscode打开的当前文件夹路径
$dir                       当前文件所在文件夹目录,后边带 / 字符
$dirWithoutTrailingSlash  当前文件所在的文件夹路径,后边不带 / 字符
$fullFileName        当前文件地址,等于 $dir$fileName
$fileName              当前文件名称
$fileNameWithoutExt    不带后缀的当前文件名称
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值
>