I am re-doing parts of my program to make it more portable. It's a lame debugger/memory dump type thing.


hexBPrint proc
push ebp
mov ebp, esp
mov eax, [ebp+8]
mov BYTE PTR [ebp-4], 0

lea ebx,hexOut+1 ; address for last character
mov ecx,2 ; number of characters
forCount: mov edx,eax ; copy pattern
and edx,0fh ; zero all but last hex digit
cmp edx,9 ; digit?
jnle elseLetter ; letter if not
or edx,30h ; convert to character
jmp endifDigit
elseLetter: add edx,'A'-10 ; convert to letter
endifDigit:
cmp BYTE PTR [ebp-4], 1
jne firstdigit
mov BYTE PTR [ebp-8],dl

firstdigit: inc BYTE PTR [ebp-4]
mov BYTE PTR [ebx],dl ; copy character to memory
dec ebx ; point at next character
shr eax,4 ; shift one hex digit right
loop forCount ; repeat

output BYTE PTR [ebp-8]

pop ebp
ret
hexBPrint endp


Here's a little info about it. An address is pushed. This proc is supposed to take a byte, convert to hex, and return. It can do that, using the variable hexOut, but that's all hexOut is used for. I want this more self-contained. Let's say in memory, there was the letter d. It would return 64. I need to move that into a BYTE variable (the only one I want) in another proc, so I need each digit seperate. I will do a mov buffer[31], 6 and mov buffer[32], 4. If I could return the 64 in a register, I can divide by 10 to get each number or if I could just return each number seperate, that would be fine, too.

The problem is, I ran out of registers to store stuff. I tried using and for extra space, but I run into the problem that the number gets stored in dl, a byte. When I output , I get (_c and not 6. I tried pushing dl in the loop, then after, popping them back out, but it doesn't like the push dl. I tried taking the first number and multiplying it by 10, then adding dl to it to get the number in eax instead of hexOut, but then I use eax, which is already in use.
Posted on 2004-11-11 16:57:41 by sjaguar13
use the stack then

hexBPrint proc

local my_little_buffer [256]:byte

push ebp
mov ebp, esp
mov eax,
mov BYTE PTR , 0

........................

now u have a 256 byte buffer on the stack easily accessable like

lea edi,my_little_buffer

sets edi to the start of the buffer, then simple indexing to store the values u need
mov byte ptr ,al

etc.. obviously requires to rewrite your code a bit

alternatively... your code is a bit bloated
using the is pointless, considering you dont actually act on it
(ecx = loop counter)





hexBPrint proc uses eax ebx ,value:dword

mov eax,value
mov ebx, offset hexout+1
mov ah,al
and eax,0f00fh

rol ah,4

donextdigitthen:

cmp al,9
ja short hexadjustmentchar

add al,'0'

jmp short storecharacter

hexadjustmentchar:

add al,'A'-10

storecharacter:

mov byte ptr [ebx],al
dec ebx

mov al,ah

cmp ebx,offset hexout
jnb donextdigitthen

ret

hexBPrint endp

eg:

push 0f0h
call hexBPrint

etc


Posted on 2004-11-11 17:31:38 by evlncrn8
I see what you mean about the ebp-4 being pointless. I was just trying stuff to see if I could actually get it to work on my own...I couldn't. The proc that calls this one does something with the numbers, and the address that is pushed into this proc doesn't have all the bytes that are going into the buffer. All I would need is a buffer that is 2 bytes big. If I make a local buffer, though, isn't that going away when when it's done with the proc?
Posted on 2004-11-11 18:00:53 by sjaguar13
You can also free up some registers so that you don't have to use local stack space. There are a few different ways to do it, I am just going to show you one. I am going to swap what ECX and EBP are used for. EBP will now be the loop variable, and CL and CH or ECX will be EBP-4 and EBP-8 respectively. I am commenting out the lines you don't need anymore.



hexBPrint proc
push ebp
; mov ebp, esp
mov eax, [ebp+8]
; mov BYTE PTR [ebp-4], 0
xor ecx,ecx ;zero EBP-4

lea ebx,hexOut+1 ; address for last character
; mov ecx,2 ; number of characters
mov ebp,2 ; number of characters
forCount: mov edx,eax ; copy pattern
and edx,0fh ; zero all but last hex digit
cmp edx,9 ; digit?
jnle elseLetter ; letter if not
or edx,30h ; convert to character
jmp endifDigit
elseLetter: add edx,'A'-10 ; convert to letter
endifDigit:
; cmp BYTE PTR [ebp-4], 1
cmp cl, 1
jne firstdigit
; mov BYTE PTR [ebp-8],dl
mov ch,dl

firstdigit:
; inc BYTE PTR [ebp-4]
inc cl
mov BYTE PTR [ebx],dl ; copy character to memory
dec ebx ; point at next character
shr eax,4 ; shift one hex digit right

; loop forCount ; repeat
dec ebp ;decrement loop variable
jnz forCount ;not zero? jump to forCount

output ch

pop ebp
ret
hexBPrint endp


In your original code ou can also unroll the loop twice and free up ECX that way, and then never push/pop EBP.

You can also shuffle other registers around to free up registers.
Posted on 2004-11-11 20:18:32 by mark_larson
sjaguar13,

There is a magic rule when you first lay out an algorithm, always start with the required number of local variables, get the code going reliably and THEN start replacing variables with registers. If you need to you can remove the stack frame to get EBP and if you are into living dangerously and understand what you are doing, you can use ESP as well.

You tend to do this style of code well along the development path once you have the algo up and going. Doing an algorithm in this order allows you to target the parts that will see the best speed increases by using registers and not waste them on variables where the speed does not matter.
Posted on 2004-11-11 20:54:54 by hutch--