我有一个相当愚蠢的问题,但我无法在任何地方找到解决方案。
我正在尝试编写一个程序,它从内存中添加(带进位)两个数字,一块一块地(32位)并将部分和写入堆栈。不幸的是,不确定为什么,循环计数器在inc %ecx
之后不会增加。 (我已经在gdb中进行了测试,%ecx
甚至在0
指令之后仍然保持inc
。
我为英特尔架构写作,但使用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 $0, %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 $0, %eax
adcl $0, %eax
push %eax
end:
mov $SYSEXIT, %eax
mov $EXIT_SUCCESS, %ebx
int $0x80
如果你还能解释它为什么会发生以及将来如何避免这个问题,我真的很感激(我还在学习,你可以看到)。另外,如果你看到其他一些错误,请告诉我。提前谢谢。
答案 0 :(得分:0)
您似乎在64位系统上汇编代码。因此,汇编程序默认为64位二进制文件。这种二进制文件中的所有代码都将作为64位代码执行。指令
.code32
使汇编程序发出32位代码,但不会改变处理器解释指令的方式;它会将您的代码解释为64位代码。要使汇编程序生成一个32位目标文件(处理器将其解释为32位代码),您需要在命令行上传递一个特殊的开关:
as --32 code.s
现在为什么跳过inc
?在x86处理器上,32位模式与64位模式非常相似,因此大多数指令都做同样的事情。大多数情况下,引入了一组新的前缀来区分32位和64位指令。由于这些新前缀没有可用的操作码,因此将操作码40
改为4f
(意为inc r32
和dec r32
)。 inc
和dec
指令仍以不同的双字节编码方式提供。因此,处理器“跳过”了您的inc
,而是更改了下一条指令。
除非你做了很奇怪的事情(比如写一个bootloader),否则你永远不需要.code32
指令。忘了它存在。请注意,您不应使用int $0x80
以64位代码进行系统调用,因为这些系统调用只接受32位指针。在64位代码中,使用syscall
进行系统调用,但请注意系统调用号和调用约定都不同。