2014-10-08 2 views
0

Я копирую код из книги, он просто читает текст из файла, конвертирует его в верхний регистр, а затем записывает в другой файл. Я просто перевел 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 

описание файла не должно быть отрицательным. Кажется, что код очень простой, но почему?

Заранее благодарен!

+0

Вы запускаете 64-разрядную программу. В 64-битном x86-64 linux системные вызовы ** не выполняются с помощью 'int' (errupt), а скорее' syscall/sysenter'. – EOF

+0

Но я пробовал другую программу, int 0x80 работает. – Dan

+0

Я только что попробовал syscall, он работает так же, как int 0x80, get -14 в качестве дескриптора файла. – Dan

ответ

0

И наконец, я нахожу ответ.

x86_64 отличается x86_32:

1 они имеют различное соглашение о вызовах (ABI), x64 передать некоторые параметры через регистры, стр. 21 из x86-64 ABI имеет хорошее объяснение.

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) 
+0

Если вы хотите вызвать это из c вместо asm, вы можете проверить http://stackoverflow.com/a/25346514/2189500. В то время как это вызывает другую функцию, существуют основы использования syscall. –

Смежные вопросы