32位汇编语言学习笔记(27)--HexDump3程序

HexDump2程序还可以再改进,通过提取公共函数到一个单独的文件,HexDump2原来的代码被分解到两个asm文件中:hexdump3.asm和
textlib.asm。

因为分解为两个文件,互相间的符号引用需要通过EXTERN和GLOBAL这两个关键字。

EXTERN声明符号是其他模块的外部符号,GLOBAL声明本模块的符号是全局符号,其他模块可见。

以下是hexdump3.asm源码,相对于书中的程序,我做了少量改动:

;  Executable name : hexdump3
;  Version         : 1.0
;  Created date    : 4/15/2009
;  Last update     : 4/20/2009
;  Author          : Jeff Duntemann
;  Description     : A simple hex dump utility demonstrating the use of
;			separately assembled code libraries via EXTERN
;
;  Build using these commands:
;    nasm -f elf -g -F stabs hexdump3.asm
;    ld -o hexdump3 hexdump3.o <path>/textlib.o
;
SECTION .bss			; Section containing uninitialized data
	BUFFLEN EQU 10
	Buff:	resb BUFFLEN

SECTION .data			; Section containing initialised data
		
SECTION .text			; Section containing code

EXTERN ClearLine, DumpChar, PrintLine, DUMPLEN

GLOBAL _start

_start:
	nop			; This no-op keeps gdb happy...
	nop
	xor esi,esi		; Clear total chars counter to 0

; 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
	jbe Done			; Jump If Equal (to 0, from compare)

; Set up the registers for the process buffer step:
	xor ecx,ecx		; Clear buffer pointer to 0

; Go through the buffer and convert binary values to hex digits:
Scan:
	xor eax,eax		; Clear EAX to 0
	mov al,byte[Buff+ecx]	; Get a char from the buffer into AL
	mov edx,esi		; Copy total counter into EDX
	and edx,0000000Fh	; Mask out lowest 4 bits of char counter
	call DumpChar		; Call the char poke procedure

; Bump the buffer pointer to the next character and see if buffer's done:
	inc ecx			; Increment buffer pointer
	inc esi			; Increment total chars processed counter
	cmp ecx,ebp		; Compare with # of chars in buffer
	jb .modTest		; If we've processed all chars in buffer...
	test esi,0000000Fh
	jnz .loadBuff
	call PrintLine
	call ClearLine
.loadBuff:
	jmp Read		; If we've done the buffer, go get more

; See if we're at the end of a block of 16 and need to display a line:
.modTest:
	test esi,0000000Fh  	; Test 4 lowest bits in counter for 0
	jnz Scan		; If counter is *not* modulo 16, loop back
	call PrintLine		; ...otherwise print the line
	call ClearLine		; Clear hex dump line to 0's
	jmp Scan		; Continue scanning the buffer

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

以下是textlib.asm的源码:

;  Executable name : textlib
;  Version         : 1.0
;  Created date    : 4/10/2009
;  Last update     : 9/2/2010
;  Author          : Jeff Duntemann
;  Description     : A linkable library of text-oriented procedures and tables
;
;  Build using these commands:
;    nasm -f elf -g -F stabs textlib.asm
;
SECTION .bss			; Section containing uninitialized data
	BUFFLEN EQU 10
	Buff	resb BUFFLEN

SECTION .data			; Section containing initialised data

; Here we have two parts of a single useful data structure, implementing the
; text line of a hex dump utility. The first part displays 16 bytes in hex
; separated by spaces. Immediately following is a 16-character line delimited
; by vertical bar characters. Because they are adjacent, they can be
; referenced separately or as a single contiguous unit. Remember that if
; DumpLin is to be used separately, you must append an EOL before sending it
; to the Linux console.

GLOBAL	DumpLin, HexDigits, BinDigits		  ;Data items
GLOBAL  DumpLength, ASCLength, FullLength, DUMPLEN	  ;Equate exports

DumpLin:	db " 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 "
DUMPLEN		EQU $-DumpLin
ASCLin:		db "|................|",10
ASCLEN		EQU $-ASCLin
FULLLEN		EQU $-DumpLin

; The equates shown above must be applied to variables to be exported:
DumpLength:	dd 3
ASCLength:	dd ASCLEN
FullLength:	dd FULLLEN


; The HexDigits table is used to convert numeric values to their hex
; equivalents. Index by nybble without a scale: [HexDigits+eax]
HexDigits:	db "0123456789ABCDEF"

; This table allows us to generate text equivalents for binary numbers. 
; Index into the table by the nybble using a scale of 4: 
; [BinDigits + ecx*4]
BinDigits:	db "0000","0001","0010","0011"
		db "0100","0101","0110","0111"
		db "1000","1001","1010","1011"
		db "1100","1101","1110","1111"

; This table is used for ASCII character translation, into the ASCII
; portion of the hex dump line, via XLAT or ordinary memory lookup. 
; All printable characters "play through" as themselves. The high 128 
; characters are translated to ASCII period (2Eh). The non-printable
; characters in the low 128 are also translated to ASCII period, as is
; char 127.
	DotXlat: 
	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

GLOBAL	ClearLine, DumpChar, Newlines, PrintLine  ;Procedures

;-------------------------------------------------------------------------
; ClearLine: 	Clear a hex dump line string to 16 0 values
; UPDATED:	4/13/2009
; IN: 		Nothing
; RETURNS:	Nothing
; MODIFIES: 	Nothing
; CALLS:	DumpChar
; DESCRIPTION:	The hex dump line string is cleared to binary 0. 

ClearLine:
	push edx	; Save caller's EDX
	mov edx,15	; We're going to go 16 pokes, counting from 0
.Poke:	mov eax,0	; Tell DumpChar to poke a '0'
	call DumpChar	; Insert the '0' into the hex dump string
	sub edx,1	; DEC doesn't affect CF!
	jae .Poke	; Loop back if EDX >= 0
	pop edx		; Restore caller's EDX
	ret		; Go home

;-------------------------------------------------------------------------
; DumpChar: 	"Poke" a value into the hex dump line string.
; UPDATED:	4/13/2009
; IN: 		Pass the 8-bit value to be poked in EAX.
;     		Pass the value's position in the line (0-15) in EDX 
; RETURNS:	Nothing
; MODIFIES: 	EAX
; CALLS:	Nothing
; DESCRIPTION:	The value passed in EAX will be placed in both the hex dump
;		portion and in the ASCII portion, at the position passed 
;		in ECX, represented by a space where it is not a printable 
;		character.

DumpChar:
	push ebx		; Save EBX on the stack so we don't trash
	push edi
; First we insert the input char into the ASCII portion of the dump line
	mov bl,byte [DotXlat+eax]	; Translate nonprintables to '.'
	mov byte [ASCLin+edx+1],bl	; Write to ASCII portion
; Next we insert the hex equivalent of the input char in the hex portion
; of the hex dump line:
	mov ebx,eax		; Save a second copy of the input char
	lea edi,[edx*2+edx]	; Calc offset into line string (ECX X 3)
; Look up low nybble character and insert it into the string:
	and eax,0000000Fh	   ; Mask out all but the low nybble
	mov al,byte [HexDigits+eax]   ; Look up the char equivalent of nybble
	mov byte [DumpLin+edi+2],al ; Write the char equivalent to line string
; Look up high nybble character and insert it into the string:
	and ebx,000000F0h	; Mask out all the but second-lowest nybble
	shr ebx,4		; Shift high 4 bits of char into low 4 bits
	mov bl,byte [HexDigits+ebx] ; Look up char equivalent of nybble
	mov byte [DumpLin+edi+1],bl ; Write the char equiv. to line string
;Done! Let's go home:
	pop edi			; Restore caller's EDI register value
	pop ebx			; Restore caller's EBX register value
	ret			; Return to caller

;-------------------------------------------------------------------------
; Newlines: 	Sends between 1-15 newlines to the Linux console
; UPDATED:	4/13/2009
; IN: 		# of newlines to send, from 1 to 15
; RETURNS:	Nothing
; MODIFIES: 	Nothing
; CALLS:	Kernel sys_write
; DESCRIPTION:	The number of newline chareacters (0Ah) specified in EDX
;		is sent to stdout using using INT 80h sys_write. This
;		procedure demonstrates placing constant data in the 
;		procedure definition itself, rather than in the .data or
;		.bss sections.

Newlines:
	pushad		; Save all caller's registers
	cmp edx,15	; Make sure caller didn't ask for more than 15
	ja .exit	; If so, exit without doing anything
	mov ecx,EOLs	; Put address of EOLs table into ECX
	mov eax,4	; Specify sys_write
	mov ebx,1	; Specify stdout
	int 80h		; Make the kernel call
.exit	popad		; Restore all caller's registers
	ret		; Go home!
EOLs	db 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10

;-------------------------------------------------------------------------
; PrintLine: 	Displays the hex dump line string via INT 80h sys_write
; UPDATED:	4/13/2009
; IN: 		Nothing
; RETURNS:	Nothing
; MODIFIES: 	Nothing
; CALLS:	Kernel sys_write
; DESCRIPTION:	The hex dump line string is displayed to stdout using 
;		INT 80h sys_write.

PrintLine:
	pushad			; Push all GP registers
	mov eax,4		; Specify sys_write call
	mov ebx,1		; Specify File Descriptor 1: Standard output
	mov ecx,DumpLin		; Pass offset of line string
	mov edx,FULLLEN		; Pass size of the line string
	int 80h			; Make kernel call to display line string
	popad			; Pop all GP registers
	ret


程序和HexDump2差不多,没有必要再分析。

makefile文件:

hexdump3: hexdump3.o textlib.o
	ld -o hexdump3 hexdump3.o textlib.o
textlib.o: textlib.asm
	nasm -f elf -g -F stabs textlib.asm
hexdump3.o: hexdump3.asm
	nasm -f elf -g -F stabs hexdump3.asm

以下是测试结果:

[root@bogon hexdump3]# make
nasm -f elf -g -F stabs hexdump3.asm
nasm -f elf -g -F stabs textlib.asm
ld -o hexdump3 hexdump3.o textlib.o
[root@bogon hexdump3]# ./hexdump3 
123456789012345
 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 0A |123456789012345.|


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值