linux - 如何在 Ubuntu11.04 中使用 NASM 维护堆栈

标签 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. 最重要的是,我使用堆栈的主要想法是使用我之前在 ebx 中推送的索引值来访问 string 变量的每个字符。 [这是强制性的。这可能吗?]

  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
    

我热切地等待您的回复。

谢谢,

最佳答案

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

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

关于linux - 如何在 Ubuntu11.04 中使用 NASM 维护堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15458914/

相关文章:

C:处理多个管道时 write() 的行为很奇怪

linux - nvidia cuda 和驱动程序版本不足

assembly - 如何为我的 Bootstrap 制作内核?

gcc - %ebp 和 %esp 的 gcc 内联汇编中的字母是什么?

linux - 如何在 vim 之后中断终端命令 | grep组合

linux - 使用通配符搜索并在同一行替换

c++ - 链接寄存器 (LR) 是否受内联或裸函数影响?

assembly - 文件打不开

linux - 从堆栈中读取多个字节到单个寄存器

汇编语言循环