从32位值转换为8位值,反之亦然,导致分段错误

时间:2019-04-07 01:32:39

标签: c linux assembly x86 nasm

这可能是我学习x86汇编语言的最后障碍。

以下子例程给我一个分段错误:

    ;================================================================= 
    ; RemCharCodeFromAToB - removes all chars between a and e from str
    ; arguments:
    ;   str - string to be processed
    ;   a   - start
    ;   e   - end
    ; return value:
    ;   n/a 
    ;-------------------------------------------------------------------
    RemCharCodeFromAToB:
        ; standard entry sequence
        push    ebp    ; save the previous value of ebp for the benefi$
        mov     ebp, esp ; copy esp -> ebp so that ebp can be used as a $   

        ; accessing arguments   
                                ; [ebp + 0] = old ebp stack frame
                                ; [ebp + 4] = return address
        mov     edx, [ebp + 8]  ; string address

        while_loop_rcc:
            mov cl, [edx]       ; obtain the address of the 1st character of the string
            cmp cl, 0           ; check the null value  

            je  while_loop_exit_rcc     ; exit if the null-character is reached

            mov al, cl ; save cl
            mov cl, [ebp + 16]      ; end-char
            push cx                 ; push end-char
            mov cl, [ebp + 12]      ; start-char
            push cx                 ; push start-char
            push ax;                ; push ch
            call IsBetweenAandB
            add esp, 12

            cmp eax, 0          ; if(ch is not between 'a' and 'e')

            je inner_loop_exit_rcc

            mov eax, edx    ; copy the current address

            inner_loop_rcc:
                mov cl, [eax+1]
                cmp cl, 0
                je  inner_loop_exit_rcc 

                mov [eax], cl

                inc eax
                jmp inner_loop_rcc
            inner_loop_exit_rcc:

            inc edx             ; increment the address
            jmp while_loop_rcc  ; start the loop again
        while_loop_exit_rcc:

        ; standard exit sequence
        mov     esp, ebp        ; restore esp with ebp
        pop     ebp             ; remove ebp from stack
        ret                     ; return the value of temporary variable    
    ;===================================================================

我怀疑从32位寄存器到8位寄存器的数据转换有问题,反之亦然。我对此的概念还不清楚。

或者,以下部分有问题

        mov al, cl ; save cl
        mov cl, [ebp + 16]      ; end-char
        push cx                 ; push end-char
        mov cl, [ebp + 12]      ; start-char
        push cx                 ; push start-char
        push ax;                ; push ch
        call IsBetweenAandB
        add esp, 12

1 个答案:

答案 0 :(得分:1)

cxax是16位寄存器,因此您的push cx ; push cx; push ax将16位值压入堆栈,总共6个字节。但是IsBetweenAandB显然期望使用32位值,并且在末尾将esp加12(而不是6)。因此,您可能想要push ecx等。

此外,您可能希望在使用eaxecx之前将它们清零。就目前而言,它们可能最初包含垃圾,并且您仅将有用的数据加载到低8位alcl中。因此,当IsBetweenAandB尝试比较完整的32位值时,您将得到错误的结果。否则,您想重写IsBetweenAandB以仅比较您关心的低字节。