flat assembler
Message board for the users of flat assembler.

flat assembler > Windows > Learning Assembly

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
What is the assembly equivalent of printf?

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 30 Mar 2017, 02:39
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
It is complicated. Especially the floating point conversions.

Would you be interested in just a subset of what printf can do as a start?

A simple conversion to decimal might be a good place to start.
Post 30 Mar 2017, 02:41
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
From the fasm sources we can find this code to print a decimal number to the console:
Code:
display_number: push ebx mov ecx,1000000000 xor edx,edx xor bl,bl display_loop: div ecx push edx cmp ecx,1 je display_digit or bl,bl jnz display_digit or al,al jz digit_ok not bl display_digit: mov dl,al add dl,30h push ecx call display_character pop ecx digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz display_loop pop ebx ret display_character: push ebx mov [character],dl push [con_handle] call [GetStdHandle] mov ebx,eax push 0 push bytes_count push 1 push character push ebx call [WriteFile] pop ebx ret
Post 30 Mar 2017, 02:46
View user's profile Send private message Visit poster's website Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
Code:
display_number: push ebx mov ecx,1000000000 xor edx,edx xor bl,bl


Just looking at this here, I see that I have a lot to learn.

We push ebx to the stack. Why?
EBX is the base point for the data section. Correct?

Then we mov 1 billion to ecx. Why?
ECX - Counter for string and loop operations

So the loop counter is equal to 1 billion?

"PC Assembly Language Paul A. Carter March 20, 2005"(page 61)-http://www.scs.stanford.edu/05au-cs240c/lab/pcasm-book.pdf
Quote:
3.2.3 The XOR operation The exclusive OR of 2 bits is 0 if and only if both bits are equal, else the result is 1 as the truth table in Table 3.3 shows. Below is a code example:
Code:
mov ax, 0C123H xor ax, 0E831H ; ax = 2912H

So therefore the edx or bl either becomes 0 or 1?

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 30 Mar 2017, 03:52
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
revolution wrote:
It is complicated. Especially the floating point conversions.

Would you be interested in just a subset of what printf can do as a start?

A simple conversion to decimal might be a good place to start.


I am interested in learning what is to be learned. However I would prefer if we pretend assembly is the only language that exists, and start like that.

I just need to know the right direction to head, and I tried to say that in my other thread. Where would you point me?

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 30 Mar 2017, 04:00
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
Don't try to interpret the register names as anything special. We can use eax or ecx or edi etc. for any purpose we wish to. In the case above ecx is not a loop counter, it is a divisor to extract the digits. It starts at 1e9 because the most significant digit of a 32-bit number can be no more than 4e9. So it extracts the first digit. Then divides the divisor by 10 (now 1e8) and extracts the next digit. And so on until the very last digit with a divisor of 1. Plus there is a bit of code to suppress leading zeros.

As for the xor: It is a shortcut used to make a register value zero. xor reg,same_reg will always leave the register as zero. You could also write mov reg,0.

And the push ebx is merely to make sure the value is not altered when returning to the caller. You can see the pop ebx just before the ret.
Post 30 Mar 2017, 04:50
View user's profile Send private message Visit poster's website Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
Code:
display_number: push ebx mov ecx,1000000000 xor edx,edx xor bl,bl ;-----^Explained------------ display_loop: div ecx push edx cmp ecx,1 je display_digit or bl,bl jnz display_digit or al,al jz digit_ok not bl

Okay so
Code:
div ecx
does what?
You said, "Then divides the divisor by 10 (now 1e8) and extracts the next digit." Why 10?

"PC Assembly Language Paul A. Carter March 20, 2005"(page 44)-http://www.scs.stanford.edu/05au-cs240c/lab/pcasm-book.pdf
Quote:
The two division operators are DIV and IDIV. They perform unsigned
and signed integer division respectively. The general format is:
Code:
div source

If the source is 8-bit, then AX is divided by the operand. The quotient is
stored in AL and the remainder in AH. If the source is 16-bit, then DX:AX
is divided by the operand. The quotient is stored into AX and remainder
into DX. If the source is 32-bit, then EDX:EAX is divided by the operand
and the quotient is stored into EAX and the remainder into EDX. The IDIV
instruction works the same way. There are no special IDIV instructions like
the special IMUL ones. If the quotient is too big to fit into its register or the
divisor is zero, the program is interrupted and terminates. A very common
error is to forget to initialize DX or EDX before division.

Code:
push edx
This is 0, right?
Code:
cmp ecx, 1 jnz display_digit

If ecx = 1 goto label display_digit.
je (jump equal = jump if ecx is 1) if I am understanding right.
Code:
or bl,bl jnz display_digit

Now here is where it gets confusing....
Code:
or bl,bl
could be this?
Code:
mov bl,0

If bl is 0, then why say if not zero go to display_digit? What is happening here?
Then this:
Code:
or al,al jz digit_ok not bl

0 out al
jump if zero to digit_ok?

Ah and then this (not) operation....
"PC Assembly Language Paul A. Carter March 20, 2005"(page 61)-http://www.scs.stanford.edu/05au-cs240c/lab/pcasm-book.pdf
Quote:

3.2.4 The NOT operation
The NOT operation is a unary operation (i.e. it acts on one operand,
not two like binary operations such as AND). The NOT of a bit is the
opposite value of the bit as the truth table in Table 3.4 shows. Below is a
code example:
Code:
mov ax, 0C123H not ax ; ax = 3EDCH

Note that the NOT finds the one’s complement. Unlike the other bitwise
operations, the NOT instruction does not change any of the bits in the FLAGS
register.


I hope my questions are not too bothersome, and I appreciate your time and effort to explain to me.

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 30 Mar 2017, 05:48
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
There are two div instructions in the source. The first is to extract the next digit, the second is to adjust ecx for the next divisor.

or bl,bl is used to set the flags. bl is not altered. So we can test if bl is zero by using or bl,bl. We can also write cmp bl,0. Note this is not the same as xor bl,bl.

jnz means jump if not zero. jz means jump if zero.
Post 30 Mar 2017, 05:55
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1172
x86 keeps track of an extra register called the FLAGS register (or EFLAGS/RFLAGS, whatever). This gets updated on specific instructions to reflect usually the output of those instructions.

For example, the zero flag is usually set if the destination (first operand) is zero, in instructions that use it.

But to really understand how it works, you need to look up the specifics of an instruction you don't know. Otherwise there's no point.

Check this site and bookmark it, it has easy to browse instructions: http://www.felixcloutier.com/x86/ (you don't have to memorize all instructions there, don't treat it as that way, just as a reference/bookmark... in time you will learn to memorize the most commonly used instructions, don't worry about it)

You can of course also download official Intel Manual but that's .pdf and harder to search...

Each instruction should say what flags it affects at the end of the description. ZF = zero flag, CF = carry flag, SF = sign flag, OF = overflow flag.

So then a jump like jz (or je which is the same instruction!) will simply jump if and only if ZF is set. ZF can be set based on previous instructions.

Code:
or reg, reg
Doesn't change the contents of 'reg' (logical OR with itself always gives the same value), but it does update the flags based on reg. A better way is to use
Code:
test reg, reg
which is the same thing.

And xor is not or.

You know the XOR operation in C? The ^ operator?

XOR = ^
OR = |
AND (or TEST) = &

That's their C equivalence.
Post 30 Mar 2017, 10:43
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
@revolution
I see my mistake of not noticing the difference between XOR and OR. Thank you for pointing that out, as well as explaining the other operations.

@Furs
I bookmarked and download the pdf. Thank you for showing me that, this is a lot to digest, and very different from learning HLLs.
Code:
display_digit: mov dl,al add dl,30h push ecx call display_character pop ecx digit_ok: mov eax,ecx xor edx,edx mov ecx,10 div ecx mov ecx,eax pop eax or ecx,ecx jnz display_loop pop ebx ret

So from what I understand, display digit does the following:
======================================
1. Copies AL (8 bit register) into DL (8 bit register)
2. Add the hex value 30 to DL
3. Push ECX to the stack
4. Call display_character
4. Pop the stored ECX
======================================
And digit_ok does:
======================================
1. Copies ECX into EAX
2. EDX is made 0
3. Store the decimal value of 10 inside ECX
4. Divide ECX*
5. Copy ECX into EAX
6. Pop EAX out of the stack (restore)
7. Compare if ECX is 0
8. If not 0, jump to display_loop
9. Pop EBX (restore)
10. End function
======================================


*(I must say I am not understanding the DIV Operation. What is it dividing by? Is this hard coded or can you specify?)

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 30 Mar 2017, 20:59
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
Like for example, what if I wanted to do 3 divided by 6, or 123 divided by 17?

Oh and I have no idea how to run that code, but learning the program flow is good. Razz
Post 30 Mar 2017, 21:09
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
C0deHer3tic: DIV is a machine instruction. Divide. You already posted the description previosuly. "If the source is 32-bit, then EDX:EAX is divided by the operand and the quotient is stored into EAX and the remainder into EDX."

When you don't understand an instruction like DIV you can always read the canonical sources from AMD / Intel. Or even a simple web search will tell you detailed answers. There is no need to wait for hours for people here to respond. You can know immediately.
Post 30 Mar 2017, 23:55
View user's profile Send private message Visit poster's website Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
My bad, I had found the answer. Should have said something. Thank you, revolution.

Was I right about the code though?

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 31 Mar 2017, 02:01
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
Step 5 should be:

5. Copy EAX into ECX
Post 31 Mar 2017, 08:14
View user's profile Send private message Visit poster's website Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
Alright, so I have been studying the registers, and the operations that can be done with them. The code you posted on how to print a decimal number to the console is now understood. However I would not know where to go from there.

What would you recommend?

I can do basic math with FASM, but cannot output anything to the console, unless of course using printf (which I learned before). I now know how to store values in the registers, being either 8 bit, 16 bit, or 32 bit. I have also learned you cannot copy registers that are different sizes.

Code:
mov eax, al ; fails mov al, ah ; both are 8 bit mov ax,ah ; fails mov ecx, ebx both are 32 bit mov ax, bx ; both 16 bit etc....


I also am learning the looping uses flags, or comparing registers.
Code:
mov ebx, 8 loop_1: dec ebx push ebx cmp ebx, 0 jnz loop_1

This will loop until Zero Flag is set.

What should I learn now?

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -


Last edited by C0deHer3tic on 31 Mar 2017, 08:53; edited 1 time in total
Post 31 Mar 2017, 08:51
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
revolution wrote:
Step 5 should be:

5. Copy EAX into ECX


Yes, I made a typo. Razz

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 31 Mar 2017, 08:52
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
The code I posted above from the fasm sources will print to the console without printf. It uses GetStdHandle and WriteFile. So you can too.

And your code for the looping example pushes ebx each time around the loop. But no associated pops are present. You will overflow the stack if you do that too many times. And note that the dec instruction also sets the Z flag so you don't need the following cmp.
C0deHer3tic wrote:
I have also learned you cannot copy registers that are different sizes.
Have a look at the movzx and movsx instructions.
Post 31 Mar 2017, 09:55
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 1172
C0deHer3tic wrote:
I bookmarked and download the pdf. Thank you for showing me that, this is a lot to digest, and very different from learning HLLs.
Just treat it as a reference. You don't memorize all APIs in C either do you? When you have doubts of an instruction use, look it up in the reference. (CTRL+F in that page)

In time, you will memorize the most commonly used instructions and "tricks", just like you memorize the most commonly used APIs.

There's no shame in having a reference at hand, I look at it all the time personally for more obscure instructions...
Post 31 Mar 2017, 12:11
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
I looked in the Pcasm book and could not find the movsx or movzx command. However I found this, http://www.c-jump.com/CIS77/ASM/DataTypes/T77_0270_sext_example_movsx.htm

I thank you both for the responses. You guys/gals are helping me.

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 01 Apr 2017, 00:20
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 15871
Location: 162173 Ryugu
Look for the Intel and AMD manuals.
Post 01 Apr 2017, 00:32
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 2004-2018, Tomasz Grysztar.

Powered by rwasa.