1

I have to be missing something obvious here, but I can't seem to find the end of a string.

My code starts off with a few calls that read as follows:

; read user input
;
    mov     eax, SYSCALL_READ       ; read function
    mov     ebx, STDIN              ; Arg 1: file descriptor
    mov     ecx, buf                ; Arg 2: address of buffer (buffer is input)
    mov     edx, BUFLEN             ; Arg 3: buffer length (defined as 256)
    int     080h

    mov     [rlen], eax             ; save length of string read

The professor gave us a shell program to work from, but I've got a pretty good handle on most of it. What's throwing me off is that I was of the impression that rlen should now contain the length of the string I'm using, but when I type the following:

mov     byte[esi + rlen], 92            ; add a zero

I get a segfault. Same, also, if I use [buf + rlen]. Neither buf nor ESI on their own cause a segfault, so it seems to me that rlen isn't doing what I think it is.

Anyone able to help me figure out what's going on?

4

1 回答 1

2

您的代码有两个问题:

mov     byte[esi + rlen], 92
  • 92 != 0. 终止的零字节 ,'\0'是一个值为零的整数。

  • rlen 是一个地址,而不是该地址的值。

因此,测试读取返回 >= 0,然后使用仍在寄存器中的返回值。

; read(2) return value still in eax

test eax, eax
jl  read_error    ; handle errors on eax less than zero.

mov esi, buf      ; mov imm32 to get the address in a register

mov  [rlen], eax  ; store return value to the rlen global

mov  byte ptr[esi + eax], 0
;or:  mov byte ptr [buf + eax], 0  ; works because the buffer is statically allocated.

jz  handle_EOF    ; flags still set from test

或者,如果您将 ecx 复制到未被 read 系统调用破坏的寄存器,则可以使用它而不是重新加载。

在一个函数中,将局部变量想象为存在于寄存器中,而内存位置只有在寄存器不足时才能溢出的地方。不要像一个非优化的编译器,当你不需要的时候存储/重新加载你的变量。这在像 x86-64 这样具有 16 个 reg 的架构上更容易;32 位 x86 受到严重限制,并且具有过时的 args-on-the-stack ABI。


如果您的缓冲区已经归零,您可以只传递 read(2) 一个比缓冲区大小小一的计数。不过,在读取返回后仅将最后一个字节归零会更好。

于 2015-09-30T11:31:02.007 回答