为什么我的汇编代码跳过一行?它一直在跳线mov AX,A
org 100h
count equ 2
A DW 5
B DW 6
Y0 DW ?
Y1 DW ?
mov AX,A
add AX,B
sub AX,count
mov Y0,AX
mov BX,B
neg BX
add BX,count
mov Y1,BX
ret
Run Code Online (Sandbox Code Playgroud)
让我们看看这些指令助记符汇编到的代码字节:
org 100h
count equ 2
05 00 A DW 5
06 00 B DW 6
00 00 Y0 DW ?
00 00 Y1 DW ?
A1 00 01 mov AX,A ;NASM "mov ax, [A]"
03 06 02 01 add AX,B ;NASM "add ax, [B]"
83 E8 02 sub AX,count
...
Run Code Online (Sandbox Code Playgroud)
代码字节在左边; 指令助记符(您向汇编程序提供的部分)位于右侧.一切看起来都不错吧?
那么,现在让我们看看当我们组装然后反汇编代码时会发生什么:
05 00 06 add ax,0x600
00 00 add [bx+si],al
00 00 add [bx+si],al
00 B8 00 01 add [bx+si+0x100],bh
05 02 01 add ax,0x102
83 E8 02 sub ax,byte +0x2
Run Code Online (Sandbox Code Playgroud)
等等......发生了什么事?!字节(左侧)是相同的,但指令助记符都是不同的!它们与你最初写的不一样!
发生的事情是,代码顶部的数据声明都由汇编器尽职尽责地翻译成字节,但反汇编程序将这些(数据)字节转换回可执行代码.它没有意识到它们是数据,因此它试图将它们解释为要执行的指令.这不仅导致错误的指令,而且还引入了一个混乱下游的帧移位突变.
所以它实际上并没有"跳过"指令mov ax, a.就计算机而言,该指令甚至不再存在.它正在执行您在第二个代码块中看到的指令.基本上,它正在执行废话.记住:在汇编程序中,一切都只是字节!
解决方案应该是显而易见的:不要将数据声明与可执行代码混合在一起.最好的办法是将数据下移到底部,在所有可执行代码下面,执行永远不会得到:
org 100h
count equ 2
mov AX,A
add AX,B
sub AX,count
mov Y0,AX
mov BX,B
neg BX
add BX,count
mov Y1,BX
ret
A DW 5
B DW 6
Y0 DW ?
Y1 DW ?
Run Code Online (Sandbox Code Playgroud)
引入空格有助于将事物分解为逻辑块,使代码更具可读性.请注意,我已将ORG指令保留在顶部,因为它需要在那里.我也没有将EQU指令移到底部.可以把它留在那里因为它只是定义了一个组装时间常数.正如您从一开始所看到的,它不会转换为生成的机器代码中的任何字节.
如果您不想因任何原因移动数据,那么您必须插入一条指令来跳过它:
org 100h
count equ 2
jmp Begin
A DW 5
B DW 6
Y0 DW ?
Y1 DW ?
Begin:
mov AX,A
add AX,B
sub AX,count
mov Y0,AX
mov BX,B
neg BX
add BX,count
mov Y1,BX
ret
Run Code Online (Sandbox Code Playgroud)