[英]Comparisons in NASM Assembly 64bit Linux
我正在学习乔纳森·巴特利特(Jonathan Bartlett)的《 从头开始编程》 ( 链接 )一书,学习汇编语言 ,我尝试将32位AT&T语法转换为64位英特尔语法版本。 我使用NASM。 现在,我正在努力使第3章的第二个程序(返回数字序列的最大数量)在64位Intel上工作。 我对代码进行了很多修改,最后设法缩小了问题的范围:这是两个数字的比较和条件跳转。 这是一个演示问题的非常简单的版本:
section .data
data: db 0
section .text
global _start
_start:
mov rdi, [data] ; if I exit here, the return value (=rdi) is 0
cmp rdi, 0
je .equals ; this is not executed
jz .equals ; this neither
jmp .notEquals
.equals:
mov rax, 60
mov rdi, 1
syscall
.notEquals: ; this is the result I get
mov rax, 60
mov rdi, 2
syscall
我从内存中读取了一个数字(数据,该数字为0)。 但是当我将此0与0进行比较时,计算机显然看到了我看不到的差异。 我确定这时rdi包含0,因为当我退出程序并获得它的返回值时,
echo $?
它显示为0。如果有人对这种神秘行为有任何暗示,我将不胜感激。 另外,如果您知道调试汇编代码的好工具,也请让我知道,因为每次都重写程序只是为了获取每时每刻的寄存器值是非常烦人的...
PS:我知道Intel语法在Linux中并不常用,但是我选择它是因为它对我来说看起来更干净,而且Vim中突出显示的源代码对于NASM而言要比对AT&T好得多;-)
mov rdi, [data]
将从内存中加载8个字节,因为那是rdi
的大小。 但是,您仅使用db
声明了1个字节。 您可以通过3种方式修复它:
dq 0
定义所有8个字节。 movzx rdi, byte [data]
设为零将字节扩展为qword。 mov dil, [data]
和cmp dil, 0
仅加载和比较单个字节。 请注意,退出代码仅提供低8位,这就是为什么看不到错误的原因。 学习改用调试器,以便您可以单步执行代码并在每个点检查寄存器。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.