我从一本书复制一些代码,它只是从文件中读取文本,转换为大写,然后写入另一个文件。我只是将32位代码翻译成Linux 64位版本。汇编代码打开文件错误
.section .data
# system call code
.equ SYS_OPEN, 5
.equ SYS_WRITE, 4
.equ SYS_READ, 3
.equ SYS_CLOSE, 6
.equ SYS_EXIT, 1
# standard file description
.equ STDIN, 0
.equ STDOUT, 1
.equ STDERR, 2
# file open options
.equ O_RDONLY, 0
.equ O_CREAT_WRONLY_TRUNC, 03101
#system call interuption
.equ LINUX_SYSCALL, 0x80
# for read file end
.equ END_OF_FILE, 0
.equ NUM_ARGUMENTS, 2
.section .bss
.equ BUFFER_SIZE, 500
.lcomm BUFFER_DATA, BUFFER_SIZE
.section .text
# stack position
.equ ST_SIZE_RESERVE, 16
.equ ST_FD_IN, -8
.equ ST_FD_OUT, -16
.equ ST_ARGC, 0
.equ ST_ARGV_0, 8 # program name
.equ ST_ARGV_1, 16 # input file name
.equ ST_ARGV_2, 24 # output file name
.global _start
_start:
mov %rsp, %rbp
sub $ST_SIZE_RESERVE, %rsp
open_file:
open_fd_in:
mov $SYS_OPEN, %rax
mov ST_ARGV_1(%rbp), %rbx
mov $O_RDONLY, %rcx
mov $0666, %rdx
# call linux
int $LINUX_SYSCALL
store_fd_in:
mov %rax, ST_FD_IN(%rbp)
open_fd_out:
mov $SYS_OPEN, %rax
mov ST_ARGV_2(%rbp), %rbx
mov $O_CREAT_WRONLY_TRUNC, %rcx
mov $0666, %rdx
int $LINUX_SYSCALL
store_fd_out:
mov %rax, ST_FD_OUT(%rbp)
# main loop
read_loop_begin:
mov $SYS_READ, %rax
mov ST_FD_IN(%rbp), %rbx
mov $BUFFER_DATA, %rcx
mov $BUFFER_SIZE, %rdx
int $LINUX_SYSCALL
# check if reach the end of the file
cmp $END_OF_FILE, %rax
jle end_loop
continue_read_loop:
push $BUFFER_DATA # buffer address
push %rax # buffer size
call convert_to_upper
pop %rax # reget buffer size
add $8, %rsp # recover stack
# write buffer to output file
mov %rax, %rdx
mov $SYS_WRITE, %rax
mov ST_FD_OUT(%rbp), %rbx
mov $BUFFER_DATA, %rcx
int $LINUX_SYSCALL
jmp read_loop_begin
end_loop:
# close file
mov $SYS_CLOSE, %rax
mov ST_FD_OUT(%rbp), %rbx
int $LINUX_SYSCALL
mov $SYS_CLOSE, %rax
mov ST_FD_IN(%rbp), %rbx
int $LINUX_SYSCALL
mov $SYS_EXIT, %rax
mov $0, %ebx
int $LINUX_SYSCALL
.equ LOWERCASE_A, 'a'
.equ LOWERCASE_Z, 'z'
.equ UPPER_CONVERSION, 'A' - 'a'
# stack relative information
.equ ST_BUFFER_LEN, 16
.equ ST_BUFFER, 24
convert_to_upper:
push %rbp
mov %rsp, %rbp
mov ST_BUFFER(%rbp), %rax
mov ST_BUFFER_LEN(%rbp), %rbx
mov $0, %rdi
# check if buffer is zero?
cmp $0, %rbx
je end_convert_loop
convert_loop:
movb (%rax, %rdi, 1), %cl
cmpb $LOWERCASE_A, %cl
jl next_byte
cmpb $LOWERCASE_Z, %cl
jl next_byte
addb $UPPER_CONVERSION, %cl
movb %cl, (%rax, %rdi, 1) # put back
next_byte:
inc %rdi
cmp %rdi, %rbx
jne convert_loop
end_convert_loop:
mov %rbp, %rsp
pop %rbp
ret
但代码无法打开文件。
[email protected]:~/labs/asm/file$ gdb ./cf
GNU gdb (Ubuntu 7.7-0ubuntu3.1) 7.7
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./cf...done.
(gdb) set args lower.txt upper.txt
(gdb) b 58
Breakpoint 1 at 0x4000c9: file cf.s, line 58.
(gdb) run
Starting program: /home/dan/labs/asm/file/cf lower.txt upper.txt
Breakpoint 1, open_file() at cf.s:58
58 mov $0666, %rdx
(gdb) x /s $rbx
0x7fffffffe8b0: "lower.txt"
(gdb) step
60 int $LINUX_SYSCALL
(gdb) step
store_fd_in() at cf.s:63
63 mov %rax, ST_FD_IN(%rbp)
(gdb) p /d $rax
$1 = -14
文件描述不应该是负值。看起来代码很简单,但是为什么?
在此先感谢!
您运行的是64位程序。在64位x86-64 linux上,系统调用不是**通过“int”(中断)完成,而是通过“syscall/sysenter”完成。 – EOF 2014-10-08 12:13:41
但我曾尝试过其他程序,int 0x80的作品。 – Dan 2014-10-08 14:30:49
我刚刚尝试了系统调用,它的工作原理与int 0x80相同,得到-14作为文件描述符。 – Dan 2014-10-08 14:44:35