It is from Chapter 10 of jeff duntemann's book on assembly language. I tried to write some code by myself but I can't get it to work properly. I need some insight please.

;Library Name:hexasc_lib;used as library for hexasc.asm

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

	HexDigits: db "0123456789ABCDEF"
	Dot: 
	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

GLOBAL ClearLine,DumpChar,PrintLine

;------------------------------------------------------------------------------------------------------------
;ClearLine:Clear a hex dump line string to 16 0 values
;Updated:
;In:
;OUT:
;MODIFIES:edx
;CALLS:DumpChar
;Description: The hex dump line string is cleared to a binary 0.

ClearLine:	push edx
		mov edx,15
	.Poke:	mov eax,0 ;poke a NULL
		call DumpChar
		sub edx,1
		;cmp edx,1 ; 1~16
		jae .Poke
		pop edx
		ret
;----------------------------------------------------------------------------------------------------------------
;DumpChar:Inserts a value into the hex dump line string
;Updated:
;In: Value to be poked into the line string is in eax, position in line string where character is to be poked in is in edx
;OUT:
;MODIFIES:eax
;CALLS:
;Description:

DumpChar:
		push ebx
		push edi
      ;First insert the input char into the ASCII portion of the dump line
                mov bl,byte [Dot+eax]
		mov byte [AscLin+edx+1],bl
		mov ebx,eax ;save a second copy of the input character
		lea edi,[edx*2+edx]
      ;Translate the input character into its corresponding hex digit
      ;extract lowest nybble and convert to hex digit
		mov al,byte [HexDigits+eax]
		and al,0fh
		mov byte [DumpLin+edi+2],al
      ;extract highest nybble and convert into corresponding hex digit
		and ebx,000000f0h;mask all bits except the highest 4 bits in bl (removes any additional bits that might be there in the higher 24 bits)
		shr bl,4
		mov bl,byte [HexDigits+ebx]
		mov byte [DumpLin+edi+1],bl

		pop edi
		pop ebx
		ret

;----------------------------------------------------------------------------------------------------------------
;PrintLine:Displays the hex dump line
;Updated:
;In: 
;OUT:
;MODIFIES:
;CALLS:
;Description: Uses the sys_write call to print a line, needs the address of the string buffer to be in ecx and length to be in edx

PrintLine:
	   pushad ;push all gp registers
	   mov eax,4
	   mov ebx,1
	   mov ecx,DumpLin
	   mov edx,DumpLen
	   Int 80h
	   popad
	   ret


;Executable:hexasc

section .bss
	BUFFLEN equ 10 ;read 10 characters from file at a time, but print out 16 entries per line
	Buff: resb BUFFLEN

section .data
	

section .text

EXTERN ClearLine,DumpChar,PrintLine

	global _start
_start:

	xor esi,esi ;clears total chars (in line) counter to 0

Read:	mov eax,3
	mov ebx,0
	mov ecx,Buff
	mov edx,BUFFLEN 
	INT 80H
	mov ebp,eax
	cmp eax,0
	je Exit

	xor ecx,ecx ;clear buffer pointer to 0
	xor edx,edx

Scan:	xor eax,eax
	mov al, byte [Buff+ecx] ;get a char from buffer to al
	mov edx,esi ;move the number of chars in counter to edx
	
	call DumpChar
	inc ecx
	inc esi
	cmp ecx,ebp
	jae Read

;Test if we are at the end of a block of 16 entries and need to display a line
	test esi,0000000fh ;if the lower 4 bits are all 1, then esi contains a value of of mod 16(0-15).Thus, ZF=0
	jnz Scan ; if ZF=1, then the lower 4 bits are not 1,hence loop back
;ecx contains Char#, esi contains number of characters on line so far
	call PrintLine
	call ClearLine
	jmp Read ; refill buffer with more data

Exit:
	call PrintLine
	mov eax,1
        mov ebx,0
        INT 80H


;makefile
hexasc:hexasc.o hexasc_lib.o
	ld -o hexasc hexasc.o hexasc_lib.o
hexasc.o:hexasc.asm
	nasm -f elf -g -F stabs hexasc.asm
hexasc_lib.o:hexasc_lib.asm
	nasm -f elf -g -F stabs hexasc_lib.asm

I hope I can get some help this time. Last time I post one thread, there was no reply. :(

It is from Chapter 10 of jeff duntemann's book on assembly language. I tried to write some code by myself but I can't get it to work properly. I need some insight please.

I hope I can get some help this time. Last time I post one thread, there was no reply. :(

All I see is some code you copied from a book and a generic plea for help... this isn't going to get you the answers you want. We want to help, but we're not mind readers.

You'll get more responses (and better ones) if you post some code you've written yourself (shorter is better), what you think it should do, what's wrong with how it's currently working, and a specific question or two about what's giving you trouble.

All I see is some code you copied from a book and a generic plea for help... this isn't going to get you the answers you want. We want to help, but we're not mind readers.

You'll get more responses (and better ones) if you post some code you've written yourself (shorter is better), what you think it should do, what's wrong with how it's currently working, and a specific question or two about what's giving you trouble.

I didnt copy that code from the book. I re-wrote it by myself without looking at the book and changed some parts. The original code from the book works perfectly fine.
As for the result, I get sth like this :

3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 (my code produces this)

when it should be
30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 0A |0123456789ABCDE.| (this is what the original code in the book gives as result)

For all the world, it looks like you're storing 16-bits per byte which is then printing as 2 unicode characters rather than 2 ascii characters. Those funny boxes with the 4 digits in them are a symbols for Unicode values that have no glyphs. For example, "31" comes out to "3" followed by that little box with 0001 inside. While it's a bit much to work completely through this code to find out where you're stuffing the extra bytes, My guess is that it's either at the file read stage or an indexing problem. Nevertheless, here are few suggestions:

1) Don't load byte data into EAX, use AL If you really need it to be 32 bits, then use a MOVZX so that you really know that the high order bits are 0.

2) Set register's to binary 0 using XOR:

Xor EAX,EAX  ;Is the same as Mov EAX,0

It's faster, smaller and independent of any word size issues.

3) Setting a buffer to all binary zeros the way you are doing it is really a mess. Use STOSB with a repeat prefix instead. For example, to Zero DumpLin:

Push ES   ;Save to restore later
  Push DS   ;There is no MOV ES,DS, so push
  Pop ES    ;And pop to set ES=DS
  MOV ECX, DumpLen
  MOV EDI, Offset DumpLin (or LEA EDI, DumpLin)
  Xor Al,AL ;Set AL to zero
  PushF     ;To save current value of Direction Flag
  CLD       ;So SI increments
  Rep Stosb ;Store byte 0 in each element of DumpLin
  PopF      ;Reset the flags (really only DF)
  Pop ES    ;And reset the ES

Some comments are in order. The first 3 lines set the ExtraSegment register to be the same as the DataSegment, which is required because Stosb addresses "ES: EDI" by default ("ES: DI" in a 16-bit segment) and cannot be overridden. If this were my code, I would set ES=DS in program main and have this as a program default. The PushF and CLD guarantees that the Direction flag is clear so that DI Increments after each repeat. The PopF restores DF to it's previous value, whatever that may be. As with DS=ES thing, I would also Clear DF as the default for the entire program so that all code in the program could rely on these values. Any section that need to change them could then handle these special cases. Note that PUSHA/POPA does not include segment registers, so you need to handle these separately. If use these defaults, then the above fragment simplifies to:

MOV ECX, DumpLen
  MOV EDI, Offset DumpLin
  Xor Al,Al ;Set AL to zero
  Rep Stosb ;Store byte 0 in each element of DumpLin

After you clean up code and track down the Unicode phantom, post again

Edited 4 Years Ago by sbesch: Fixed problem with Unicode Glyphs not printing

This article has been dead for over six months. Start a new discussion instead.