无法在 32 位代码中递增寄存器

Cannot increment register in 32 bit code

我遇到了一个相当愚蠢的问题,但我无法在任何地方找到解决方案。

我正在尝试编写一个程序,它从内存中逐个(32 位)添加(带进位)两个数字,并将部分和写入堆栈。不幸的是,不知道为什么,for 循环的计数器在 inc %ecx 之后没有递增。 (我已经在 gdb 中测试过,并且 %ecx 甚至在 inc 指令之后就保持在 0

我为 Intel 架构编写,但使用 AT&T 语法(我在这里别无选择)。

.code32

SYSEXIT = 1
EXIT_SUCCESS = 0

.align 32
.data
nr1:
    .long 0xF0000111, 0x000B0000
nr2:
    .long 0x10000333, 0x000A000F
size:
    .long 0x00000002

.text
.global _start
_start:
mov [=10=], %ecx                 #initialization of counter
movl size(,%ecx,4), %edi     #moving size (amount of 32-bit pieces) to %edi

addition:
movl nr1(,%ecx,4), %eax    #moving one piece 
movl nr2(,%ecx,4), %ebx    #(from address of nr1 + (value of %ecx * 4 bytes)

adcl %ebx, %eax                 #add with carry
push %eax                       #push the result

inc %ecx                        #increment counter
cmp %edi, %ecx                  #compare %edi (==2) with counter (%ecx)
je overflow                     # if %edi == %ecx
jmp addition                    # else back to addition loop

overflow:   #in case when last sum had an overflow (CF==1)
mov [=10=], %eax                   
adcl [=10=], %eax
push %eax

end:
mov $SYSEXIT, %eax
mov $EXIT_SUCCESS, %ebx
int [=10=]x80

如果您还可以解释为什么会发生这种情况以及将来如何避免该问题,我将不胜感激(如您所见,我仍在学习)。另外,如果您看到其他错误,请告诉我。提前致谢。

您似乎是在 64 位系统上汇编您的代码。因此,汇编程序默认为 64 位二进制文​​件。此类二进制文件中的所有代码都将作为 64 位代码执行。指令

.code32

使汇编程序发出 32 位代码,但不改变处理器解释指令的方式;它会将您的代码解释为 64 位代码。要使汇编器生成 32 位目标文件(处理器会将其解释为 32 位代码),您需要在命令行上传递一个特殊开关:

as --32 code.s

为什么 inc 被跳过了?在 x86 处理器上,32 位模式与 64 位模式非常相似,因此大多数指令做同样的事情。大多数情况下,引入了一组新的前缀来区分 32 位和 64 位指令。由于没有可用于这些新前缀的操作码,操作码 404f(意思是 inc r32dec r32)被重新利用。 incdec 指令仍然以不同的双字节编码提供。因此,处理器“跳过”了您的 inc 而是更改了下一条指令。

除非您正在做非常奇怪的事情(例如编写引导加载程序),否则您永远不需要 .code32 指令。忘记它的存在。请注意,您不应使用 int [=21=]x80 在 64 位代码中执行系统调用,因为这些系统调用仅接受 32 位指针。在64位代码中,系统调用使用syscall,但注意系统调用号和调用约定是不同的。