Повреждение памяти в сборке? - PullRequest
2 голосов
/ 04 октября 2010

В настоящее время у меня есть программа сборки, которая смоделирована после системной функции hexdump в Linux.По сути, он печатает текущий номер строки, преобразует двоичные значения в шестнадцатеричные строки, а также показывает текущий ASCII, связанный с шестнадцатеричной строкой.

У меня проблема с системой печати номеров строк.Функция будет работать только тогда, когда другие части кода закомментированы - в противном случае она дает неверные результаты.Однако я не понимаю, почему две части кода должны оказывать какое-либо влияние друг на друга, поскольку используемые регистры очищаются.

Когда работает функция PrintLineNum, она печатает текущий номер строки слева отстрока

000000E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |r Linux, using N.| 
000000F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |ASM 2.05,.;    d.| 
0000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  |emonstrating the.| 
0000011 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  | conversion of b.| 

Однако, когда функциональность для печати шестнадцатеричной строки вновь включена, она начинает "пропускать".

000000E 72 20 4C 69 6E 75 78 2C 20 75 73 69 6E 67 20 4E  |r Linux, using N.| 
000000F 40 53 4D 20 32 2E 30 35 2C 0A 3B 20 20 20 20 64  |ASM 2.05,.;    d.| 
0000000 65 6D 6F 6E 73 74 72 60 74 69 6E 67 20 74 68 65  |emonstrating the.| 
0000000 20 63 6F 6E 76 65 72 73 69 6F 6E 20 6F 66 20 62  | conversion of b.| 
0000002 69 6E 60 72 79 20 76 60 6C 75 65 73 20 74 6F 20  |inary values to .| 
0000003 68 65 78 60 64 65 63 69 6D 60 6C 20 73 74 72 69  |hexadecimal stri.| 
0000004 6E 67 73 2E 0A 3B 20 20 20 20 49 74 20 60 63 74  |ngs..;    It act.

Я не уверен, почему печать шестнадцатеричнойСтрока влияет на количество строк - насколько я могу судить, две операции независимы.Любые советы, предложения или улучшения помогут.Обратите внимание, что часть этого кода взята из «Языка ассемблера - шаг за шагом» Дюнтманна.Я только что добавил номера строк и распечатку ASCII.Я отметил проблемный раздел кода ниже.

Спасибо за любую помощь!

SECTION .bss                    ; Section containing uninitialized data

        BUFFLEN equ 16          ; We read the file 16 bytes at a time
        Buff:   resb BUFFLEN    ; Text buffer itself

SECTION .data                   ; Section containing initialised data

        ; storage location for line number
        LineNStr: dd "000001"
        LINNLEN equ $-LineNStr

        LineNum: dd 1
        LINLEN equ $-LineNum

        ; storage location for ASCII string
        TextStr:        db " |................ | ",10
        TEXTLEN equ $-TextStr

        ; storage location for hex string
        HexStr: db " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ",
        HEXLEN equ $-HexStr

        ; conversion tables
        Digits: db "0123456789ABCDEF"

        Ascii:  
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 20h,21h,22h,23h,24h,25h,26h,27h,28h,29h,2Ah,2Bh,2Ch,2Dh,2Eh,2Fh
                db 30h,31h,32h,33h,34h,35h,36h,37h,38h,39h,3Ah,3Bh,3Ch,3Dh,3Eh,3Fh
                db 40h,41h,42h,43h,44h,45h,46h,47h,48h,49h,4Ah,4Bh,4Ch,4Dh,4Eh,4Fh
                db 50h,51h,52h,53h,54h,55h,56h,57h,58h,59h,5Ah,5Bh,5Ch,5Dh,5Eh,5Fh
                db 60h,61h,62h,63h,64h,65h,66h,67h,68h,69h,6Ah,6Bh,6Ch,6Dh,6Eh,6Fh
                db 70h,71h,72h,73h,74h,75h,76h,77h,78h,79h,7Ah,7Bh,7Ch,7Dh,7Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh
                db 2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh,2Eh

SECTION .text                   ; Section containing code

; All done! Let's end this party:
Done:
        mov eax,1               ; Code for Exit Syscall
        mov ebx,0               ; Return a code of zero
        int 80H                 ; Make kernel call

global  _start                  ; Linker needs this to find the entry point!

_start:
        nop                     ; This no-op keeps gdb happy...

; Read a buffer full of text from stdin:
Read:
        mov eax,3               ; Specify sys_read call
        mov ebx,0               ; Specify File Descriptor 0: Standard Input
        mov ecx,Buff            ; Pass offset of the buffer to read to
        mov edx,BUFFLEN         ; Pass number of bytes to read at one pass
        int 80h                 ; Call sys_read to fill the buffer
        mov ebp,eax             ; Save # of bytes read from file for later
        cmp eax,0               ; If eax=0, sys_read reached EOF on stdin
        je Done                 ; Jump If Equal (to 0, from compare)

; Set up the registers for the process buffer step:
        mov esi,Buff            ; Place address of file buffer into esi
        mov edi,HexStr          ; Place address of line string into edi
        xor ecx,ecx             ; Clear line string pointer to 0

; Go through the buffer and convert binary values to hex digits:
Scan:
        xor eax,eax             ; Clear eax to 0

; Convert text into ASCII string:
        mov al,byte [esi+ecx]           ; Get current location into al
        mov bl,byte [Ascii+eax]         ; Use lookup table to perform conversions
        mov byte [TextStr+ecx+2],bl     ; Write to ASCII text block

; Here we calculate the offset into the line string, which is ecx X 3
        mov edx,ecx             ; Copy the pointer into line string into edx
;       shl edx,1               ; Multiply pointer by 2 using left shift
;       add edx,ecx             ; Complete the multiplication X3
        lea edx,[edx*2+edx]     ; The lea operation performs a combination of the two operations above

; Get a character from the buffer and put it in both eax and ebx:
        mov al,byte [esi+ecx]   ; Put a byte from the input buffer into al
        mov ebx,eax             ; Duplicate the byte in bl for second nybble

;;;;;;;;;;;;;;;;;; When this section is commented out, the line printout works properly
; Look up low nybble character and insert it into the string:
        and al,0Fh                 ; Mask out all but the low nybble
        mov al,byte [Digits+eax]   ; Look up the char equivalent of nybble
        mov byte [HexStr+edx+2],al ; Write the char equivalent to line string

; Look up high nybble character and insert it into the string:
        shr bl,4                ; Shift high 4 bits of char into low 4 bits
        mov bl,byte [Digits+ebx] ; Look up char equivalent of nybble
        mov byte [HexStr+edx+1],bl ; Write the char equivalent to line string
;;;;;;;;;;;;;;;;;; When this section is commented out, the line printout works properly

; Bump the buffer pointer to the next character and see if we're done:
        inc ecx         ; Increment line string pointer
        cmp ecx,ebp     ; Compare to the number of characters in the buffer
        jna Scan        ; Loop back if ecx is <= number of chars in buffer

; Print the current line number prior to printing any other information
        Call PrintLineNum ; print line number function

; Write the line of hexadecimal values to stdout:
        mov eax,4               ; Specify sys_write call
        mov ebx,1               ; Specify File Descriptor 1: Standard output
        mov ecx,HexStr          ; Pass offset of line string
        mov edx,HEXLEN          ; Pass size of the line string
        int 80h                 ; Make kernel call to display line string

; Write the line of ASCII values to stdout:
        mov eax,4               ; Specify sys_write call
        mov ebx,1               ; Specify File Descriptor 1: Standard output
        mov ecx,TextStr         ; Pass offset of line string
        mov edx,TEXTLEN         ; Pass size of the line string
        int 80h                 ; Make kernel call to display line string
        jmp Read                ; Loop back and load file buffer again

PrintLineNum:
; Clear out the registers
        xor eax,eax
        xor ebx,ebx

; Get data into registers
        mov al,byte [LineNum]   ; Put a byte from the input buffer into al
        mov ebx,eax             ; Duplicate the byte in bl for second nybble

; Look up low nybble character and insert it into the string:
        and al,0Fh                 ; Mask out all but the low nybble
        mov al,byte [Digits+eax]   ; Look up the char equivalent of nybble
        mov byte [LineNStr+6],al ; Write the char equivalent to line string

; Look up high nybble character and insert it into the string:
        shr bl,4                ; Shift high 4 bits of char into low 4 bits
        mov bl,byte [Digits+ebx] ; Look up char equivalent of nybble
        mov byte [LineNStr+5],bl ; Write the char equivalent to line string

; Increment line number
        mov eax,[LineNum]
        inc eax
        mov [LineNum],eax

; Write the line number to stdout:
        mov eax,4               ; Specify sys_write call
        mov ebx,1               ; Specify File Descriptor 1: Standard output
        mov ecx,LineNStr        ; Pass offset of line string
        mov edx,LINNLEN
        int 80h                 ; Make kernel call to display line string
        ret

1 Ответ

5 голосов
/ 08 октября 2010

В вашем коде есть ошибка «по одному».

Проблема в этой строке:

    jna Scan        ; Loop back if ecx is <= number of chars in buffer

, что означает, что вы обойдете цикл 17 раз,а не 16. На это намекает комментарий ruslik (исходная строка TextStr состоит из 16 точек, за которыми следует пробел, так почему пробел заменяется?).

Причина, по которой он разбивает нумерацию строк:что mov byte [HexStr+edx+2],al в отмеченном разделе переполняется HexStr на 17-й итерации и записывается в таблицу Digits.Он также разбивает шестнадцатеричный дамп (посмотрите на первую пунктирную строку: a из demonstrating был сброшен как 60, а не 61).

Попробуйте:

    jb  Scan        ; Loop back if ecx is < number of chars in buffer

вместо.

...