汇编代码打开文件错误

时间:2014-10-08 10:42:08

标签: assembly

我从一本书中复制了一些代码,它只是从文件中读取文本,转换为大写,然后写入另一个文件。我只是将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

但代码无法打开文件。

dan@ubuntu:~/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

文件描述不应该是负值。似乎代码很简单,但为什么呢?

提前致谢!

1 个答案:

答案 0 :(得分:0)

最后,我找到了答案。

x86_64与x86_32不同:

1他们有不同的调用约定(ABI),x64通过寄存器传递一些参数,p。 x86-64 ABI中的21个有一个很好的解释。

2他们有不同的系统调用代码。检查this post。在x86_32中,打开的系统调用代码是5,而在x86_64中它是2

代码应如下所示:

  mov $SYS_OPEN, %rax        # open operation, code is 2
  mov ST_ARGV_1(%rbp), %rdi  # input file name
  mov $O_RDONLY, %rsi        # flags
  #mov $0666, %rdx            # mode
  # call linux 
  syscall
store_fd_in:
  mov %rax, ST_FD_IN(%rbp)
相关问题