我在使用 16 位寄存器完成大学作业时遇到问题。我尝试运行的代码如下:
myArray db 1,2,3,4; declared in the correct section
;-----------------
mov si, myArray
mov ax, [si] ; segfault here
sub ax, [si+1]
mov [si+3], ax
和
mov dx, 1234h
push dx
mov dx, 0ABCDh
push dx
mov bp, sp
mov ax, ss:[bp]
两者都会导致分段错误。但是,当我使用 ESI 和 RBP 寄存器运行相同的代码时,它的汇编没有问题。
我在 Ubuntu 22.04.3 的虚拟机上运行它。我从一位朋友那里听说(不确定这有多可靠),x86 64 位可能会阻止对某些 16 位寄存器的直接访问,这就是我遇到问题的原因。我向教授提出了这个问题,但他们驳回了我,说这可能是我的语法错误。
我尝试寻找解决方案,但没有成功。我最初使用的是 WSL,认为是问题所在,于是改用 VirtualBox VM,但没有效果。
mov eax, 1 mov ebx, 0 int 0x80
从评论已经确定您正在编写一个32位程序。
使用16位寄存器保存16位值是可以的,但不能保存地址!您的
mov si, myArray
和 mov bp, sp
正在加载不完整的地址。您可以通过 mov esi, myArray
和 mov ebp, esp
获得完整地址。movzx
(带有零扩展的 MOVe)。
mov ax, [si]
和sub ax, [si+1]
同时寻址两个字节大小的数组元素,但mov [si+3], ax
还写入数组后面的字节!这可能是另一个变量,并且会以这种方式被破坏。目前尚不清楚第一个片段应该实现什么,但重写如下:
mov esi, myArray
movzx eax, word [esi] ; -> AX = 0201h (EAX = 00000201h)
sub ax, [esi+1] ; -> AX = FEFFh (EAX = 0000FEFFh)
mov ???
在
mov ax, ss:[bp]
中提到BP作为基地址已经使CPU使用SS段寄存器。这是默认值。无需显式添加段覆盖 ss:
,这可能会消耗额外的字节,具体取决于汇编器。push 1234ABCDh
movzx eax, word [esp] ; -> AX = 0ABCDh (EAX = 0000ABCDh)