我從一本書複製一些代碼,它只是從文件中讀取文本,轉換爲大寫,然後寫入另一個文件。我只是將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