2010-10-04 9 views
2

J'ai actuellement un programme d'assemblage qui est modélisé après la fonction du système hexdump sous Linux. Essentiellement, il imprime le numéro de ligne en cours, convertit les valeurs binaires en chaînes hexadécimales et affiche également l'ASCII en cours associé à la chaîne hexadécimale.Corruption de la mémoire dans l'assemblage?

Je rencontre un problème avec mon système d'impression de numéros de ligne. La fonction ne fonctionnera que lorsque d'autres parties du code seront mises en commentaire, sinon cela produira des résultats incorrects. Cependant, je ne vois pas pourquoi les deux parties du code devraient avoir un effet l'un sur l'autre, puisque les registres utilisés sont effacés.

Lorsque la fonction PrintLineNum fonctionne, il imprime le numéro de ligne à gauche de la ligne

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.| 

Cependant, lorsque la fonctionnalité d'impression la chaîne hexadécimale est réactivée, il commence à « sauter ».

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. 

Je ne sais pas pourquoi l'impression de la chaîne hexadécimale affecte le nombre de lignes - les deux opérations sont aussi indépendants autant que je peux dire. Tout conseil, suggestion ou amélioration aiderait. Veuillez noter qu'une partie de ce code provient de la «langue d'assemblage de Duntemann - étape par étape». Je viens d'ajouter les numéros de ligne et l'impression ASCII. J'ai marqué la section problématique du code ci-dessous.

Merci pour toute aide!

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 "ABCDEF" 

     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

Vous tapez actuellement 17 caractères en mode texte (le dernier étant toujours 0x2e). – ruslik

Répondre

5

Vous avez une erreur «off-by-one» dans votre code.

Le problème est sur cette ligne:

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

ce qui signifie que vous allez dans la boucle 17 fois, plutôt que 16. Ceci est fait allusion à par le commentaire de ruslik (la chaîne TextStr d'origine est de 16 points a suivi par un espace, alors pourquoi l'espace est-il remplacé?).

La raison pour laquelle il rompt la numérotation des lignes est que mov byte [HexStr+edx+2],al dans la section marquée déborde de HexStr à la 17e itération et écrit dans le tableau Digits. Il casse aussi la décharge hexadécimale (regardez la première ligne brisée: le a de demonstrating a été jeté comme 60, pas 61).

Essayez:

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

à la place.

+0

Oui, c'est absolument correct. Ce n'est en fait pas mon propre code avec l'erreur - l'erreur provient du code que l'auteur a inclus dans le livre. – BSchlinker

Questions connexes