如何在Ubuntu 11.04中使用NASM维护堆栈

时间:2013-03-17 08:29:42

标签: linux assembly x86 stack nasm

对于我的项目工作,我测试了一段代码片段。我发现由于堆栈的使用,此代码段出现了分段错误。但是,我必须使用堆栈解决它任何人都可以帮我找出问题?我的程序将显示字符串变量的第二个字符。我的代码片段如下:

section.data
  string db "test",10,0
  msg2   db "%c",10,0
main:

xor eax,eax
mov eax, string
mov ebx,1    ; suppose I want to get the second character of string. SO I store the index of that character in ebx

pusha
push eax
push ebx
add esp,8
popa

pop dword[ebx]   ;  **I assume that this following 3 lines arise segmentation fault**   
pop eax          ;
mov bl,[eax+ebx] ; I want to move the fisrt character to BL using the index value stored in ebx which i popped just.

pusha
push ebx
call putchar
add esp,4
popa

pusha
push msg2
call printf
add esp,4
popa

在此,为了您的善意考虑,我想明确指出,此代码段的目的是了解如何操作堆栈。

在这里,@ nrz最近给了我一个关于以下代码的想法,我在这里编辑了上面的代码:

  section.data
    string db "test",10,0
    msg2   db "%c",10,0
  main:
    xor eax,eax
    mov eax, string
    mov ebx,1  ; suppose I want to get the second character of string. SO I store the index of that character in ebx
    mov   eax,string
    movzx eax,byte [eax]
    push  eax        ; these push and pop are for solving it using the stack,
    pop   ebx
    pusha
    push ebx
    call putchar
    add esp,4
    popa
    pusha
    push msg2
    call printf
    add esp,4
    popa

我的查询是特定的:

  1. 我会给出索引值。它应该在ebx寄存器中吗?

  2. 最重要的是,我使用堆栈的主要思想是使用我之前在string中推送的索引值来处理ebx变量的每个字符。 [这是强制性的。有可能吗?]

  3. 我想将输出存储在一个8位寄存器中。

    所以我的所有想法都是这样的:

    mov al, [string+ebx]   ;is it possible?
    

    我必须从堆栈中获取ebx的值。我将在ebx中设置一个值,然后在push ebx中设置一个值,在mov al,[string+ebx]时,我将pop ebx获取mov指令的值。更有可能的说明如下:

     pop ebx  
     mov al,[string+dword[ebx]]  ;which is a wrong statement shown by NASM
    
  4. 我急切地等待你的回应。

    感谢你,

1 个答案:

答案 0 :(得分:0)

代码中存在一些错误和不必要的指示:

mov eax, string  ; this line makes eax point to string, but...
xor eax,eax      ; this line zeroes eax immediately. delete this line.
mov ebx,1        ; this line is unnecessary, but does not cause problems.

pusha            ; unnecessary.
push eax         ; unnecessary.
push ebx         ; unnecessary.
add esp,8        ; unnecessary.
popa             ; unnecessary.

pop dword[ebx]   ; [1] = [esp], esp = esp+4, probably causes segmentation fault.
pop eax          ; eax = [esp], esp = esp+4
mov bl,[eax+ebx]

编辑:打印所有字符,只需遍历字符串:

section.data
  string db "test",10
  string_length equ $-string ; number of characters in the string.
                             ; no zero needed in the end of the string.
  msg2   db "%c",10,0
main:
    xor eax,eax      ; eax is the index to the string.

char_loop:
    push dword [eax+string]      ; push 4 first characters into stack.
    and  dword [esp], 0x000000ff ; x86 is little-endian, so 1st character
                                 ; is the lowest byte.
    pop  ebx                     ; pop the ASCII code of the character into ebx.

    pushad
    push ebx
    call putchar
    add esp,4
    popad

    inc eax
    cmp eax,string_length
    jb  char_loop

修改:使用ebx作为索引来匹配问题中的更改的新代码。

section.data
  string db "test",10
  string_length equ $-string ; number of characters in the string.
                             ; no zero needed in the end of the string.
  msg2   db "%c",10,0
main:
    xor  eax,eax             ; zero eax, for putchar.
    xor  ebx,ebx             ; ebx is the index to the string.

char_loop:
    ;push dword [ebx+string]      ; push 4 first characters into stack.
    ;and  dword [esp], 0x000000ff ; x86 is little-endian, so 1st character
    ;                             ; is the lowest byte.
    ;pop  eax                     ; pop the ASCII code of the character into ebx.

    mov   al,[ebx+string]         ; this is the normal way to do it.
                                  ; the above 3 instructions do it "using stack",
                                  ; as requested in the question.
    pushad
    push eax
    call putchar
    add esp,4
    popad

    inc ebx
    cmp ebx,string_length
    jb  char_loop