Преобразование из 32-битных в 8-битные значения и наоборот в сборке, приводящее к ошибке сегментации - PullRequest
0 голосов
/ 07 апреля 2019

Это, наверное, мое последнее препятствие в изучении языка ассемблера 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 Ответ

1 голос
/ 07 апреля 2019

cx и ax являются 16-разрядными регистрами, поэтому ваши push cx ; push cx; push ax помещают в стек 16-разрядные значения, всего 6 байтов.Но IsBetweenAandB, очевидно, ожидает 32-битные значения, и вы добавляете 12 к esp в конце (вместо 6).Итак, вы, вероятно, хотели push ecx и т. Д.

Кроме того, вы, вероятно, хотите обнулить eax и ecx перед их использованием.В существующем виде они изначально содержат мусор, и вы загружаете только полезные данные в младшие 8 бит al и cl.Таким образом, когда IsBetweenAandB пытается сравнить полные 32-битные значения, вы получите ложные результаты.Или же вы хотите переписать IsBetweenAandB, чтобы сравнить только младшие байты, которые вас интересуют.

...