在函数中使用STDIN不能正常工作

时间:2018-09-10 19:02:27

标签: assembly nasm x86-64 system-calls

我在汇编中编写了此示例程序,以使用syscall和功能进行训练。第一个函数printString正常工作,它打印给定的字符串。问题出在readString函数中,它应该读取STRLEN个字符,然后返回:

section .data
; Define standard constants.
LF equ 10 ; line feed
NULL equ 0 ; end of string
EXIT_SUCCESS equ 0 ; success code
STDIN equ 0 ; standard input
STDOUT equ 1 ; standard output
SYS_read equ 0 ; read
SYS_write equ 1 ; write
SYS_exit equ 60 ; terminate
; Define some strings.
STRLEN equ 10
pmpt db "Enter Text: ", NULL
newLine db LF, NULL
section .bss
chr resb 1
inLine resb STRLEN+2 ; total of 52
section .text
global _start
_start:
; Display prompt.
mov rdi, pmpt
call printString

mov rdi, inLine
mov rsi, STRLEN
mov rdx, chr
call readString

; Output the line to verify successful read
mov rdi, rax
call printString

; Example done.
exampleDone:
mov rax, SYS_exit
mov rdi, EXIT_SUCCESS
syscall

; ******************************************************
; Generic procedure to display a string to the screen.
; String must be NULL terminated.
; Algorithm:
; Count characters in string (excluding NULL)
; Use syscall to output characters
; Arguments:
; 1) address, string
; Returns:
; nothing
global printString
printString:
push rbx
; Count characters in string.
mov rbx, rdi
mov rdx, 0
strCountLoop:
cmp byte [rbx], NULL
je strCountDone
inc rdx
inc rbx
jmp strCountLoop
strCountDone:
cmp rdx, 0
je prtDone
; Call OS to output string.
mov rax, SYS_write ; system code for write()
mov rsi, rdi ; address of char's to write
mov rdi, STDOUT ; standard out
; RDX=count to write, set above
syscall ; system call
; String printed, return to calling routine.
prtDone:
pop rbx
ret

global readString
readString:
push rbx
push r12
push r11

mov rcx, rsi
; Read characters from user (one at a time)
mov rbx, rdi ; inLine addr
mov r11, rdx
mov r12, 0 ; char count
readCharacters:
    mov rax, SYS_read; system code for read
    mov rdi, STDIN; standard in
    lea rsi, byte[r11] ; address of chr
    mov rdx, 1 ; count (how many to read)
    syscall ; syscall
    mov al, byte [r11] ; get character just read
    cmp al, 10 ; if linefeed, input done
    je readDone
    inc r12 ; count++
    cmp r12, rcx ; if # chars > STRLEN
    jae readCharacters ; stop placing in buffer
    mov byte [rbx], al ; inLine[i] = chr
    inc rbx ; update tmpStr addr
    jmp readCharacters
readDone:
mov al, bl

pop r11
pop r12
pop rbx
ret

在最后第六行mov al, bl中,我将结果返回到main函数。但是,当我传递到printString时,它出现了分段错误。我使用gdbrbx的{​​{1}}寄存器中进行了调试,但是实际上它不包含字符串,但是为什么呢?如果我在主字符串的x/s $rbx中编写代码,则它可以正常工作。我认为当我传递参数以及在函数中推送和弹出寄存器时,我失去了一些东西。

编辑 这是寄存器的内容:

readString

它发生在第93行的分段错误中,这是对(gdb) info register rax 0x1 1 rbx 0x402011 4202513 rcx 0x4010a0 4198560 rdx 0x1 1 rsi 0x402010 4202512 rdi 0x0 0 rbp 0x0 0x0 rsp 0x7fffffffe1b0 0x7fffffffe1b0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x206 518 r12 0x0 0 r13 0x0 0 r14 0x0 0 r15 0x0 0 rip 0x4010a0 0x4010a0 <readCharacters+26> eflags 0x206 [ PF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 的系统调用。

您能帮我吗? 预先感谢

0 个答案:

没有答案