运行名为time2.asm
的程序集x86-64程序时收到错误消息。
我使用的是Ubuntu x86-64。
执行sys_open系统调用后,rax寄存器将其值更改为-14 - 这意味着出现错误或“错误地址”。
我的代码用于打开一个名为“a.txt”的文件,检查是否发生错误,如果没有,请关闭该文件。
我的代码:
section .data
file_name equ "a.txt"
section .text
global _start
_start:
;--------------------------------------------------------------------
; first step- I open a file called a.txt.
mov rax, 2 ; sys_open
mov rdi, file_name
mov rsi, 0
mov rdx, 0644q
syscall
;right after this syscall (sys_open), rax value changes to -14.
cmp rax,0
jl error ;checks for error
mov rdi,rax
mov rax,3 ; sys_close
syscall
;----------------------------------------------------------------------------
error: mov rax,60
mov rdi,0
syscall ; exit program
file_name equ "a.txt"
将file_name
定义为仅汇编时数数字constant1。这个指令出现在哪个部分并不重要;它不会将任何字节汇集到输出中。 equ
纯粹是一个装配时间不变的东西。与%define
字符串替换类似,但它会将表达式计算为当场的数字。 (这对涉及$
的表达很重要,如msglen equ $ - msg
。)
但是你需要在内存中使用你的字符串,并向系统调用一个指向0终止(隐式长度)C字符串的指针。系统调用接口只接受指针,而不是值;否则它将无法处理超过8个字节的文件名。 (或32位系统中的4个字节)。
从而
default rel
section .rodata ; read-only data doesn't need to be in read-write .data
file_name: db "a.txt", 0 ; the 0 terminator is important, this is a C string.
section .text
...
lea rdi, [file_name] ;or mov rsi, file_name for the inefficient way
在x86-64中将静态地址放入寄存器的标准方法是RIP相对LEA。 (default rel
)。 mov edi, symbol
适用于非PIE可执行文件,但基本上没有理由使用mov rdi, symbol
(10字节mov r64, imm64
)。
脚注1:
NASM允许在接受数字文字的任何上下文中使用多字符常量。例如mov rax, 'a.txt'
完全等同于mov rax, 0x7478742e61
,因此mov [mem], rax
会将字符串放入内存(因为x86是little-endian),后跟3个字节的零。
file_name equ "a.txt"
完全等同于file_name equ 0x7478742e61