NASM 汇编 64 位 Linux 中的比较
Comparisons in NASM Assembly 64bit Linux
我正在通过 Jonathan Bartlett 的书 Programming from the Ground Up (Link) 学习汇编程序,我尝试将 32 位 AT&T 语法转换为 64 位 Intel 语法版本.我使用 NASM。现在我正在努力让第 3 章的第二个程序(return 数字序列的最大数量)在 64 位英特尔上工作。我修改了很多代码,最终设法缩小了问题的范围:这是两个数字的比较和条件跳转。这是一个演示问题的非常简单的版本:
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 因为当我在那里退出程序并得到它的 return 值
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 位,这就是您看不到错误的原因。学习改用调试器,这样您就可以单步执行代码并检查每个点的寄存器。
我正在通过 Jonathan Bartlett 的书 Programming from the Ground Up (Link) 学习汇编程序,我尝试将 32 位 AT&T 语法转换为 64 位 Intel 语法版本.我使用 NASM。现在我正在努力让第 3 章的第二个程序(return 数字序列的最大数量)在 64 位英特尔上工作。我修改了很多代码,最终设法缩小了问题的范围:这是两个数字的比较和条件跳转。这是一个演示问题的非常简单的版本:
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 因为当我在那里退出程序并得到它的 return 值
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 位,这就是您看不到错误的原因。学习改用调试器,这样您就可以单步执行代码并检查每个点的寄存器。