News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

Need some clarification on basic MASM concepts

Started by masterori, February 07, 2016, 04:50:39 PM

Previous topic - Next topic

dedndave

there are several ways to do that
keep in mind, the last byte should be a 0 (null terminator)
also - any DWORD ASCII decimal value, signed or unsigned, plus the null terminator, will fit into a 12-byte buffer
so, you might start with

    mov     edi,esp     ;EDI points to the end of buffer
    push    0
    sub     esp,8


or, you could do this, and add code to 0 the last byte later on
    mov     edi,esp     ;EDI points to the end of buffer
    sub     esp,12


notice that ESP maintains 4-byte aligned in both cases

masterori

Maybe I'm a bit dense, but I don't think you're answering my question...
If I do something like this

    push  0011

Will it push the ASCII character 51 onto the stack?. The ASCII 51 is the representation of 3. If it does not, how do I get it to put 51 instead of 0011, 3 or whatever it puts in the stack?

dedndave

    push    11

will push a decimal 11, dword size (3 zero bytes)
dword is the default for push in 32-bit code
decimal is the default radix for masm, so the 11 is seen as 11, or 0Bh

if you want to get 51 on the stack
    push    51
again, it will be a dword, and 51 will be seen as decimal (ASCII for "3")

masterori

So even if I use     push 0011b it'll still push 11? Is there a way to automatically convert a binary into ascii?

As per my original question, the question wants to push each digit of 38507 onto the stack one by one. I'm given 1001011001101011b to start with. So I thought of using 'div' by 10000, 1000, 100, ... to get each of the digits of 38507 in binary form. Or does that not work - dividing a binary by a decimal?

dedndave

11b specifies binary - that overrides the default - that is 3 in decimal

ok - i am telling you that pushing individual bytes isn't going to work
you can push 4 bytes at a time

or - you can create stack space by multiples of 4 bytes, then fill those bytes individually
that is why i used sub esp

you did not state that the values had to be pushed
you stated they had to be on the stack when done

masterori

I understand everything that you've posted. But I'm still trying to figure out if there's a way to get the ascii representation of each digit because that's what the question is asking for. It shows a stack similar to the one I posted on the previous page.

Quote from: dedndave on February 13, 2016, 12:05:16 PM
you did not state that the values had to be pushed
you stated they had to be on the stack when done
I don't understand you. How can they be on the stack when they weren't pushed on?

Again, 1001011001101011b is 38507 in binary. So again going back to my question on the first page, can I take 1001011001101011b and divide by 10000 (decimal) to get 3 decimal then (somehow) get the ascii representation of it and push it onto the stack?

I want to know if there's some kind of conversion that gets the ascii of a binary or decimal value. The reason is because DIV stores the quotient in AX and the remainder in DX, so I was going to loop it until DX is 0. This would give me 3, 8, 5, 0, 7 respectively. Now all that's left is to convert those to ascii then push (or if pushing automatically converts it over to ascii then that's fine).

jj2007

Quote from: masterori on February 13, 2016, 12:36:25 PMcan I take 1001011001101011b and divide by 10000 (decimal) to get 3 decimal then (somehow) get the ascii representation of it and push it onto the stack?

Yes. Get Olly to understand what this code does:
include \masm32\include\masm32rt.inc
.code
start:
  mov eax, 123456789 ; or 38507
  mov esi, esp ; we need a "permanent" reg32 like esi here
  mov ecx, 10
  .Repeat
cdq
div ecx
add edx, "0"
push edx
  .Until !eax
  .Repeat
print esp, 32 
pop eax
  .Until esp>=esi
  inkey chr$(13, 10, "That was cool, right?")
  exit
end start

masterori

Quote from: jj2007 on February 13, 2016, 01:27:35 PM

add edx, "0"
push edx
 

This does the conversion to ascii? You can add a char with a binary like that?

dedndave

#23
let's deal with the stack

there are many ways to access data on the stack
generally, the CPU maintains a stack pointer
for 32-bit code, it is named ESP (Extended Stack Pointer)
it is a register that holds a pointer into the stack area (an address)

when you PUSH a dword onto the stack, the value in ESP is decreased by 4, and the data is written to that address
when you POP a dword, the value at [ESP] is popped to whatever destination you specified,
and ESP is increased by 4

now, if we want to "reserve" space on the stack without PUSH, we can manipulate ESP
    sub     esp,12
it's almost as though we had pushed 3 dwords
but - the data on the stack is not altered (i.e., it is garbage that was there before)

later on, we can write data to those 12 bytes (our ASCII string, for example)
and still later, we can access that data directly, or by using POP

the EBP (Extended Base Pointer) register is also used to access data on the stack
ESP changes whenever items are added or removed from the stack
EBP does not change when items are added or removed
instead, it is generally a fixed pointer that is temporary on a per-subroutine basis
i have written many posts about the use of EBP - use the forum search tool to find them

dedndave

now, conversion from binary to ASCII decimal string is an entirely different subject
we usually write a subroutine to perform this function
we might pass to the subroutine the binary value to convert, and a pointer to (address of) the string buffer
whether that buffer is on the stack or in one of the data sections is inconsequential

a simple method is an adaptation of Horner's Rule
for the decimal value of 38507 decimal...
we repeatedly divide by 10
for each division, the remainder (technically, it's called a modulus) becomes the next digit (last digit first)
it will be from 0 to 9 (binary)
to convert that digit to ASCII, we add 30h (or use the OR instruction)
now, the byte is from 30h to 39h - the ASCII decimal numbers
the quotient is saved for the next pass
the process is repeated until the quotient is 0 (no more digits)

38507 / 10   >> quotient = 3850, modulus = 7 >> 7 + 30h = 37h (the last digit in the string)
3850 / 10   >> quotient = 385, modulus = 0 >> 0 + 30h = 30h
  385 / 10   >> quotient = 38, modulus = 5 >> 5 + 30h = 35h
   38 / 10   >> quotient = 3, modulus = 8 >> 8 + 30h = 38h
    3 / 10   >> quotient = 0, modulus = 3 >> 3 + 30h = 33h (the first digit in the string)


for each pass of the loop, a digit is stored, and the pointer is decremented

as you can see digits come out of the loop one byte at a time
because the stack is maintained as dwords, accessing bytes with PUSH is not practical

jj2007

Quote from: masterori on February 13, 2016, 02:05:12 PM
Quote from: jj2007 on February 13, 2016, 01:27:35 PM

add edx, "0"
push edx

This does the conversion to ascii? You can add a char with a binary like that?

Yes, you can :t

If you had followed my advice above to use Olly, you would have already found out how the stack looks like before starting the code:
Address   Hex dump                                         comments
0018FF7C  00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00|
0018FF8C  8A 33 44 76|00 E0 FD 7E|D4 FF 18 00|82 98 C5 77| stack is 0018FF8C


Now you start the loop, pushing (using my example 123465789)
9+"0" = 00000039h
8+"0" = 00000038h
7+"0" = 00000038h


etc. After 4 times push edx, the same memory area looks like this:
Address   Hex dump                                         comments
0018FF7C  36 00 00 00|37 00 00 00|38 00 00 00|39 00 00 00| stack is 0018FF7C
0018FF8C  8A 33 44 76|00 E0 FD 7E|D4 FF 18 00|82 98 C5 77|


Now, in the second loop, we use print esp, 32 (with the 32 just being a space added to the output)
The print macro expects a pointer to a memory area containing a zero-delimited string. So is esp "a pointer to a memory area containing a zero-delimited string"?
0018FF7C  36 00

With each pop eax, esp advances a dword (4 bytes), so in round 2 print esp uses 37 00
etc etc.

Your turn. I won't help you any more unless you can prove that you opened your executable in Olly and hit the F8 key to see all this happening.

dedndave

    add     edx,"0"

is the same as

    add     edx,30h

these instructions would also work

    add     dl,30h

    or      dl,30h

if i am not mistaken, the instructions with EDX are 3 bytes in length
the ones with DL are only 2 bytes

you would still PUSH EDX (not PUSH DL)