我是如何学习Java的~dosbox下装载运行汇编程序

在前面的章节中不仅搭建了dosbox汇编环境,同时还介绍了mov、add、sub、push、pop等汇编指令,也了解了CPU是怎么操控数据和运行指令的。但对于一个功能来说,是需要不同的指令组合才能实现的,同时对于汇编源程序的运行,还需要对其编译生成包含机器码的目标文件,之后通过连接功能最终生成可执行文件。

对于最终生成的可执行文件,可以通过dosbox把可执行文件中的机器指令装载到内存中,同时运用R和T指令来查看相应寄存器和执行程序。

dosbox装载过程如下:

  1. 找到一段起始地址为 段地址(SA):0000H 的容量足够的空闲空间
  2. 在该内存空间的前256个字节中创建一个程序段前缀(PSP)的数据区,dos需要利用该数据区来和被加载的程序进行通信
  3. PSP后的内存空间用来装载指令。此时指令的段地址为SA+10H,偏移地址依旧为0,按照前面章节介绍的寻址方式,10H*16 即为256个字节
  4. 将该内存的段地址存入寄存器DS中,同时设置CS:IP指向程序指令的开始地址

该分配的内存地址如下图所示:
我是如何学习Java的~dosbox下装载运行汇编程序_第1张图片
现有以下功能:
计算寄存器AX和BX的和,结果存放AX中,并交换AX和BX的值:

assume cs:codesg

codesg segment

	mov ax, 1000H
	mov bx, 2000H
	add ax, bx
	mov ss, bx
	mov sp, 0
	push ax
	push bx
	pop ax
	pop bx
	
	mov ax, 4C00H
	int 21H
	
codesg ends

end

通过以上汇编代码,可以分析汇编源程序的组成语法:

1-伪指令

伪指令没有对应的机器码,由编译器执行,在这段源程序中,出现了三种伪指令:

	assume
	...
	codesg segment
		...
	codesg ends
	...
	end

segmentends 是成对出现的伪指令,用来说明一个段的开始和结束。此处定义了一个代码指令段,段名称为 codesg 。
一个汇编程序可以由多个段组成,不同的段可以被用来存放代码、数据或栈空间来使用。一个有意义的汇编程序至少要有一个代码段。

assume 伪指令用来说明某一寄存器和某一定义的段的关联,在此处把段寄存器 cs 和代码段 codesg 联系起来。

end 伪指令表示一个汇编程序的结束。编译器在编译汇编程序的过程中,如果碰到了伪指令 end ,就会结束对源程序的编译。

2-汇编指令

汇编指令有对应的机器码,编译器会把汇编指令翻译为机器码以供CPU执行。

当执行一个程序后,需要把CPU的控制权交还给使它得以运行的程序,这个过程称为程序返回。在汇编中,可用以下指令实现程序返回:

mov ax, 4C00H
int 21H

3-标号

汇编程序中,除了汇编指令和伪指令外,还有一些标号,如 codesg 。这个标号作为段的名称,指代了一段指令的地址。

分析完汇编源程序后,下面需要对该源程序进行编译连接为可执行文件,使用dosbox装载到内存中并执行:

  • 打开dosbox,执行masm.exe编译源程序,源程序可以在挂载目录的任意位置,后缀名也可以指定:
    我是如何学习Java的~dosbox下装载运行汇编程序_第2张图片
    编译过程中,一般会有两类错误:

    1.存在Severe Errors,此时需要检查源程序是否有书写和语法错误
    2.找不到所给出的源程序文件。在此示例中,C:\asm\a.asm的实际路径是E:\dosbox\a\a.asm。此处路径若写错,就会出现此错误。

    当编译成功时,若不指定目标文件的位置,会在挂载目录下生成一个目标文件:a.obj。

  • 执行link.exe,连接目标文件生成可执行文件:
    我是如何学习Java的~dosbox下装载运行汇编程序_第3张图片
    在连接时,如不指定可执行文件的生成位置,则默认在挂载目录下生成。
    连接程序输出了一条没有栈段的警告,在此可以忽略这个警告。

dosbox装载运行

对于生成的可执行文件,我们可以直接双击运行,但为了能看到每一步的执行情况,可以使用debug命令在dosbox装载程序,并通过R指令查看寄存器的值:
装载
最下面显示当前CS:IP指向的指令:mov ax, 1000,通过T命令可以执行一条指令,并显示当前各个寄存器的值:
执行指令
此时寄存器AX的值为:1000H
执行下一条指令: mov bx, 2000H,并查看寄存器的值:
执行指令
此时寄存器BX的值为:2000H
执行下一条指令:add ax, bx,并查看寄存器的值:
执行指令
此时寄存器AX的值为:3000H
执行下一条指令:mov ss, bx,并查看寄存器的值:
执行指令
此时寄存器SS的值为2000H,同时注意到下一条指令为 PUSH AX ,并不是 MOV SP, 0 ,此处涉及到中断机制,先不做过多说明。

执行接下来的指令,一直到程序返回前,并查看寄存器的值:
我是如何学习Java的~dosbox下装载运行汇编程序_第4张图片
此时AX=2000H,BX=3000H,已顺利完成AX和BX的数据交换,然后执行完剩余的指令即可。

目录
上一章
下一章

你可能感兴趣的:(汇编,Java,C语言,我是如何学习Java的)