我正在使用GAS汇编程序为linux x86_64编写一个helloworld程序,下面是我在AT&T语法。
#.intel_syntax noprefix
.section .data
msg:
.ascii "hello worldn"
.section .text
.globl _start
_start:
movq $1, %rax
movq $1, %rdi
movq $msg, %rsi
movq $12, %rdx
syscall
movq $60, %rax
movq $0, %rdi
syscall
这个作品和印刷"你好世界"。以下是intel语法:
.intel_syntax noprefix
.section .data
msg:
.ascii "hello worldn"
.section .text
.globl _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, 12
syscall
mov rax, 60
mov rdi, 0
syscall
这编译和运行良好,但不会打印"helloworld"。我假设错误在mov rsi, msg
?如果是,正确的语法是什么?
尝试mov rsi, offset msg
。gas使用类似masm的语法,其中mov rsi, msg
将msg
的内容移动到rsi
而不是移动地址。必须使用offset
关键字来避免此问题。
如果你想用英特尔语法编程,我建议你选择一个更好的汇编程序,比如nasm。
您可以使用AT&T语法反汇编程序(如objdump -d
(,以查看GAS.intel_syntax
中的mov rsi, msg
汇编为mov msg, %rsi
,即来自32位绝对地址的64位加载。
或者使用objdump -d -Mintel
查看工作版本的英特尔语法反汇编。
GDB具有set disassembly-flavor intel
或att,因此您甚至可以在一个调试会话内翻转。
BTW,您应该使用RIP相对LEA将64位静态地址获取到寄存器中。它比mov r64, imm64
更有效率
lea msg(%rip), %rsi # AT&T
lea rsi, [msg + rip] # GAS .intel_syntax
lea rsi, [rel msg] ; NASM
(但在静态标签位于虚拟地址空间的低31位的位置相关可执行文件中,其效率低于mov r32, imm32
。(
## In x86-64 position-dependent executables on Linux
mov $msg, %esi # AT&T
mov esi, OFFSET msg # GAS .intel_syntax
mov esi, msg ; NASM
请注意,OSX将静态地址放在低32之外,因此即使在可执行文件中,您的地址也是64位的。无法将.data中的变量移动到Mac x86程序集的寄存器