我一直在尝试自学一些 32 位 x86 (NASM)。我试图让用户输入文件名,打开/创建文件,然后获取用户的消息并将该消息写入文件。我已经在 GDB 中检查过了,所有的系统调用都正确返回了。程序运行后,文件似乎创建不正确,并且没有写入任何内容。我 ahev 看到了其他一些类似的问题,但我的代码似乎与他们的代码几乎相同,所以我似乎无法弄清楚到底发生了什么。
这是我的菜鸟代码:
global _start
section .data
fmsg: db "Enter Filename: ", 0
.len: equ $ - fmsg
umsg: db "Enter message: ", 0
.len: equ $ - umsg
buff: times 50 db 0 ;array for user string
.blen: equ $ - buff
fname: times 50 db 0 ;array for filename
.flen: equ $ - fname
;modes
O_RDONLY: db 0 ;read-only
O_WRONLY: db 1 ;wirte-only
O_RDWR: db 2 ;read and write
;flags
O_CREAT: dw 100o ;create file if file doesnt exists
O_TRUNC: dw 1000o ;truncate file
O_APPEND: dw 2000o ;append to file
section .bss
fd: resd 1 ;file descriptor
bret: resd 1 ;read buffer return value
fret: resd 1 ;read filename return value
tmp: resd 1 ;temp 4 byte variable
section .text
_start:
fprompt: ;Print prompt
mov eax, 0x4 ;syscall 4 - write()
mov ebx, 0x1 ;file desc 1 - stdout
mov ecx, fmsg ;print message
mov edx, fmsg.len ;length of message
int 80h ;syscall interupt
filein:
mov eax, 0x3 ;syscall 3 - read()
mov ebx, 0x0 ;file desc 0 - stdin
mov ecx, fname ;dst buffer
mov edx, fname.flen ;length of buffer
int 80h ;syscall interupt
mov [fret], eax ;save return value to file return variable
cmp eax, edx ;read max bytes or more?
jb fileopen ;jmp is bytes read < max
mov bl, [ecx+eax-1] ;grab last byte @ last index before '\0'
cmp bl, 10 ;does it = '\n' ?
je clean1
inc DWORD [fret] ;len++
clean1: ;loop to clear excess input, if any
mov eax, 0x3 ;syscall 3 - read()
mov ebx, 0x0 ;file desc 0 - stdin
mov ecx, tmp ;temp buffer
mov edx, 0x1 ;read only 1 byte
int 80h ;;syscall interupt
test eax, eax ;EOF?
jz fileopen ;Yes, jump to pback
mov al, [tmp] ;put character into lower 8 bits of EAX
cmp al, 10 ;is it = to lf ?
jne clean1 ;no, jump to begining of loop
fileopen:
mov eax, 0x05
mov ebx, fname ;filename
or ecx, O_CREAT ;if it doesn't exist create the file
or ecx, O_TRUNC ;truncate
mov edx, O_WRONLY ;write only
int 80h ;syscall interupt
mov [fd], eax ;save file descripor
prompt2:
mov eax, 0x4 ;syscall 4 - write()
mov ebx, 0x1 ;file desc 1 - stdout
mov ecx, umsg ;print message
mov edx, umsg.len ;length of message
int 80h
userin:
mov eax, 0x3 ;syscall 3 - read()
mov ebx, 0x0 ;file desc 0 - stdin
mov ecx, buff ;dst buffer
mov edx, buff.blen ;length of buffer
int 80h ;syscall interupt
mov [bret], eax ;save return value to buff return variable
cmp eax, edx ;read max bytes or more?
jb writetofile ;jmp is bytes read < max
mov bl, [ecx+eax-1] ;grab last byte @ last index before '\0'
cmp bl, 10 ;does it = '\n' ?
je clean2
inc DWORD [bret] ;len++
clean2: ;loop to clear excess input, if any
mov eax, 0x3 ;syscall 3 - read()
mov ebx, 0x0 ;file desc 0 - stdin
mov ecx, tmp ;temp buffer
mov edx, 0x1 ;read only 1 byte
int 80h ;syscall
test eax, eax ;EOF?
jz writetofile ;Yes, jump to pback
mov al, [tmp] ;put character into lower 8 bits of EAX
cmp al, 10 ;is it = to lf ?
jne clean2 ;no, jump to begining of loop
writetofile:
mov eax, 0x4 ;syscall 4 - write()
mov ebx, [fd] ;file desc 1 - stdout
mov ecx, buff ;print message
mov edx, [bret] ;length of message
int 80h ;syscall interupt
closefile:
mov eax, 0x6 ;syscall 6 - close()
mov ebx, [fd] ;file desc
int 80h ;syscall interupt
exit: ;return 0
mov eax, 1 ;syscall 1 - exit()
mov ebx, 0 ;return val
int 80h ;syscall interupt
文件“test.txt?”出现并且还显示为可执行文件,即使我只为文件设置了读/写。即使我试图打开它,那里也什么也没有。有什么想法吗?另外正如我所提到的,我是新手,正在自学,所以如果您有任何关于改进该计划其他领域的好建议,请告诉我! :)
最佳答案
我们在以下三行代码中有多个错误(或一个大错误):
or ecx, O_CREAT ;if it doesn't exist create the file
or ecx, O_TRUNC ;truncate
mov edx, O_WRONLY ;write only
问题:
寄存器 ecx
和 edx
在这些行之后有什么值?
您对 ecx
寄存器执行了两个 或
操作,但显然它在那一刻没有被初始化!
这意味着您可以确定代表 O_CREAT
和 O_TRUNC
的位(无论这些值是什么意思 - 见下文)已设置,但您不知道哪些值其他位有。
O_WRONLY
位应该在 ecx
中设置,而不是在 edx
中设置。 edx
应该包含所需的文件模式。
不幸的是,有两种不同类型的汇编程序——我不知道 NASM 是哪种类型:
- 一种类型的汇编程序会将第一条指令解释为:
或 ecx, [O_CREAT]
- 另一种类型会将其解释为:
或 ecx, address_of(O_CREAT)
在第一种情况下,指令 mov edx, O_WRONLY
将读取以 O_WRONLY
字节开始的四个字节到 edx
寄存器中,所以 edx
的值为 0x400201
(O_CREAT*0x10000+O_RDWR*0x100+O_WRONLY)。
在第二种情况下,edx
将包含 O_WRONLY
的地址而不是值。
这个值在任何情况下都是错误的。
关于linux - 创建/写入文件 x86 Linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45786253/