这可能是我学习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

?
完整的asm代码is here
C++代码is here
生成文件is here

最佳答案

cxax是16位寄存器,因此push cx ; push cx; push ax在堆栈上推送16位值,总共6个字节。但是IsBetweenAandB显然需要32位的值,在结尾处添加12到esp(而不是6)。所以你可能想要push ecx等。
另外,在使用它们之前,您可能需要将eaxecx归零。就目前的情况来看,它们最初可能包含垃圾,而您只需将有用的数据加载到低8位alcl中。因此,当IsBetweenAandB尝试比较完整的32位值时,将得到错误的结果。或者您想重写IsBetweenAandB以只比较您关心的低字节。

关于c - 从32位值转换为8位值,反之亦然,导致段错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/55554890/

10-11 18:54