汇编代码跳过一条线?

时间:2017-06-20 00:12:02

标签: assembly x86 x86-16

为什么我的汇编代码会跳过一行?它一直在跳过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

2 个答案:

答案 0 :(得分:6)

让我们看看代码字节这些指令助记符将汇总到:

               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
...

代码字节在左边;指令助记符(您向汇编程序提供的部分)位于右侧。一切看起来都不错吧?

好吧,现在让我们看看当我们组装然后反汇编代码时会发生什么:

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

等等......发生什么事了?!字节(左侧)是相同的,但指令助记符都是不同的!它们与你最初写的不一样!

发生的事情是,代码顶部的 data 声明都由汇编程序尽职尽责地翻译成字节,但是反汇编程序将这些(数据)字节转换回可执行代码。它没有意识到它们是数据,因此它试图将它们解释为要执行的指令。这不仅导致了错误的指令,而且还引入了一个混淆了下游所有内容的frameshift mutation

所以它实际上不是"跳过"指令mov ax, a。就计算机而言,该指令不再是那里。它正在执行您在第二个代码块中看到的指令。基本上,它正在执行废话。记住:在汇编程序中,一切都只是字节!

解决方案应该是显而易见的:不要将数据声明与可执行代码混合在一起。最好的办法是将数据下移到 bottom ,在所有可执行代码之下,执行永远不会得到:

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 ?  

引入空格有助于将事物分解为逻辑块,使代码更具可读性。请注意,我已将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

答案 1 :(得分:0)

问题在于,在您的代码中,您将操作代码与数据定义混合在一起。这是完全错误的,因为您的汇编程序将假设这些数据定义是助记符,弄乱代码。要查看它,只需下载十六进制编辑器并查看代码的十六进制格式。然后找一个反汇编程序并尝试反汇编hex格式代码。您将看到反汇编程序显示的代码与您在代码中键入的代码有很大不同。换句话说,不会跳过行mov AX, A,而不是假设它是另一个操作码。