flat assembler
Message board for the users of flat assembler.

Index > Windows > I have the assembler, now what?

Goto page 1, 2, 3, 4, 5, 6  Next
Author
Thread Post new topic This topic is locked: you cannot edit posts or make replies.
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 25 Mar 2017, 22:09
Hello everyone,

I am an experienced programmer in several languages and now I have decided it is time to tackle assembly. I chose FASM to start with. Reasons are that I was able to compile the code on my system which is Windows 8, 64 bit of course. I have tried many assembly language books which unfortunately require me to run the compiled code in emulators. The example code in FASM works; compiling and running smoothly. Most of it is GUI, which is okay, however console is more ideal to me.

I would like a beginner tutorial to start assembly in Fasm with a basic teaching like a simple hello world to print to console until it covers the entire scope of the assembly language with examples and exercises preferably. NO GUI PLEASE.

Example in C would be:

Code:
#include <stdio.h> //for the printf

int main() // This is the program entry. It can't run otherwise.
{
     printf("Hello world!\n"); // Prints Hello World! on the screen. The \n makes a newline.
     return 9; // Stops the program with code 9
}
    

Is this at all possible? I would appreciate any responses. If this question was asked another place, forgive my unfortunate mistake. Very Happy

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



Joined: 06 Nov 2011
Posts: 257
Trinitek 26 Mar 2017, 00:32
I'm not aware of any tutorials that use FASM. Certainly, there are tutorials that exist for NASM on Linux, but I don't know how good they are.

Since you're looking for some basic console I/O, you can hook the C runtime library, MSVCRT, and use your bread 'n butter printf functions and etc.

Here's a complete program that calculates dot products that I wrote for RosettaCode.org: https://gist.github.com/Trinitek/268dc4a56cb08dea7a1e It hooks MSVCRT and invokes printf using the 'invoke' macro provided in win64a.inc. Hopefully this is a good starting point.

Edit:
Actually, perhaps this isn't very great. Laughing I just realized there's no comments.
Post 26 Mar 2017, 00:32
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 26 Mar 2017, 02:39
I would love to learn just pure assembly code. Is that at all possible? I can see many example programs in FASM which execute perfectly, but are all GUI. I am trying to stick with console base programming.Smile

I don't need printf. That was merely a poor example to how things are explained in C programming.

I took a look at your code. All it did was confuse me. Would it be too much to ask if you took the time to explain each command? Shocked

I understand this:

Code:
.calculate: // A label 
        mov r8, rcx     // mov rcx to r8
        add r8, 8       // add 8 to r8 (r8 now is equal to x + 8 )
        mov r9, rdx   // rdx -> r9
        add r9, 8      // add 8 to r9
        mov rcx, rax // etc
        mov rax, 0
        mov rdx, 0
    


However the other stuff could be explained.

I am looking for a beginner tutorial for windows assembly. Something I can run in windows 8. No emulators needed. And no Linux. I need to learn this on windows. I don't want to hook C or any other language. Is this at all possible?

If I have to use a different assembler, then so be it. Can anyone point me to that one? I have tried following many tutorials and they are all concentrated around DOS or Linux. I see it pointless to program in a language, if all I can do is run it on a system not used in today's computing. 16 bit is hardly compatible now.


Thank you for your response. Wink

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



Joined: 06 Nov 2011
Posts: 257
Trinitek 26 Mar 2017, 04:20
You might not need printf, but some sort of output would be nice, no? Wink Debuggers hurt the eyes.

Confused So, I've just discovered that this code crashes in Win10, yet worked fine on my Win7 machine, and it works perfectly in my debugger. If anybody could help me figure out what's going on, that would be great.

I've updated the Gist with a commented version: https://gist.github.com/Trinitek/268dc4a56cb08dea7a1e#file-dotproductcommented-asm

...

Edit: After reading through this several times, I just realized that I wrote this with positive integers in mind, while I have negative numbers in some of the vectors. Good grief.


Last edited by Trinitek on 26 Mar 2017, 08:50; edited 1 time in total
Post 26 Mar 2017, 04:20
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 26 Mar 2017, 04:46
Thank you for the time to comment your code! Very Happy

I am still curious for a beginner course to assembly language, but that was helpful. Razz

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 26 Mar 2017, 04:46
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8357
Location: Kraków, Poland
Tomasz Grysztar 26 Mar 2017, 22:08
You may try searching through the Examples and Tutorials section. There is this nice Intro to x86 Assembly with FASM that uses console in Windows. It is 32-bit, but if you are just starting out, it might be good to start with 32-bit examples (there are definitely more of them available) and then move to 64 bits, because all that knowledge from the 32-bit world is not going to become obsolete, it is just built upon and expanded in the 64-bit case.
Post 26 Mar 2017, 22:08
View user's profile Send private message Visit poster's website Reply with quote
Trinitek



Joined: 06 Nov 2011
Posts: 257
Trinitek 27 Mar 2017, 07:06
Ah, it was a stack alignment issue that was crashing my dot product example. The Gist files have been updated accordingly.

Truth be told, the move from 32-bit and 64-bit is just learning the differences and caveats between the two; they're compatible 99% of the time. But I tried my best to look for a decent 64-bit tutorial since I knew you explicitly did not want 32-bit.
Post 27 Mar 2017, 07:06
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8357
Location: Kraków, Poland
Tomasz Grysztar 27 Mar 2017, 08:03
Trinitek wrote:
Truth be told, the move from 32-bit and 64-bit is just learning the differences and caveats between the two; they're compatible 99% of the time. But I tried my best to look for a decent 64-bit tutorial since I knew you explicitly did not want 32-bit.
I think that this particular combination - Windows console and 64-bit code - was not a popular choice for writing tutorials.
Post 27 Mar 2017, 08:03
View user's profile Send private message Visit poster's website Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2545
Furs 27 Mar 2017, 17:06
The 64-bit calling convention (for some reason referred as "ABI") is a pathetic trash design to begin with, especially the one by Microsoft.

I suggest you stick with 32-bit until you get more proficient with assembly, because calling functions is very clean in 32-bit: just push the parameters and call it. You don't even have to clean the stack yourself, since the functions do it in the Windows API (which is a very sane and clean design). Not like you need an emulator for 32-bit code, since it runs perfectly fine.

Then you can realize how much of a mess the 64-bit ABI is. Stack alignment is just one of the many idiotic design decisions. Since 0.1% of functions will even use vectorized SSE crap (AVX doesn't even require alignment anymore, about time), yet you waste so much stack space for *every* single function because of the ABI, and we're stuck with this for eternity. (keep in mind, this will NOT work for larger vector instructions, so technically it's a total waste of space if you want to make AVX+ code, because you have to realign the stack anyway)

Furthermore, and this applies both to SYSV and MS calling conventions for 64-bit, they seem keen on passing parameters in registers yet eax is completely unused for this purpose, yet trashed by the function???? (return value). WTF is wrong with those idiots Confused

eax should have been THE most important register to use as a parameter, considering that usually you use a function's return value as a "handle" or something else to a new function -- which would require NO register moves or pushes at all!

Lastly, and this concerns the MS calling convention... what the actual hell is with the Shadow Space? This is by far the most idiotic design decision in existence.

Wow, you save instructions in a small function that has to spill the stupid register parameters on the stack (why isn't such a function tagged with a different calling convention that uses stack parameters then...?) and presumably uses no other local variables, thus you don't have to adjust the stack in those functions.

Just for those 0.5% of functions above, what we get as drawback? Much bigger code for every single function call (because you have to use MOV to place parameters on the stack, or PUSH dummy space (4 pushes) for the shadow space for each call) which translates to a much bigger performance hit on top of bloated code. Very sane engineers!

And every single function will suffer, while only a tiny minority will benefit, overall much much worse performance (in terms of what the entire shit "saves" us, if it was insignificant then why even pass parameters in registers in the first place?).

I really get sick when I see people say how x64 is a "clean" ABI when it's totally the opposite. It's idiotic and a total disaster in terms of clean engineering.

It's one of the reasons I use asm more than I should probably (I like C code too), because compiler vendors are OBSESSED with not providing us a custom calling convention ability via extensions. They just love to shove this idiotic ABI down our throats, or have to resort to asm for some 64-bit code. Maybe I should attempt to write a GCC plugin for this to get rid of this idiotic ABI in C code.

/end rant sorry Razz
Post 27 Mar 2017, 17:06
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 27 Mar 2017, 19:33
I appreciate all of your replies. They are all very helpful.

Tomasz Grysztar, Furs, and Trinitek

Thank you for the link to the tutorial, the interesting rant, as well as the useful comments to your code, Trinitek. They were all very helpful to say the least.

I don't want to eliminate 32 bit programming, I just need the 32 bit code to run in a windows 8 environment. I rather learn 32 bit first, before delving into 64bit.

Can you tell me why this does not print out "Hello World!" ?
Code:

format PE console

entry start

include 'win32a.inc'

Hello db 'Hello World!',0

start:
        mov eax, Hello
        call [printf]
        call [ExitProcess]


; Import section
section '.idata' import data readable
 
library kernel32, 'kernel32.dll', \
        msvcrt,'msvcrt.dll'

import kernel32, \
       ExitProcess,'ExitProcess'
 
import  msvcrt, \
        printf, 'printf'      


    


Instead it prints this:

Code:
P §░◄Φv÷♣╨☻■⌂►t Φ☼
    


Shocked

Sincerely, C0deHer3tic

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



Joined: 06 Nov 2011
Posts: 257
Trinitek 27 Mar 2017, 19:46
Parameters go on the stack in the 32-bit stdcall convention. Wink Like so...
Code:
start:
    push Hello
    call [printf]
    push 0
    call [ExitProcess]    
The callees are responsible for cleaning up the stack, so you're not getting your hands dirty just calling them.
Post 27 Mar 2017, 19:46
View user's profile Send private message Reply with quote
system error



Joined: 01 Sep 2013
Posts: 670
system error 27 Mar 2017, 19:51
Code:
start:
    push Hello
    call [printf]
    add esp,4
    push 0
    call [ExitProcess]    


add esp,4 is required because printf is a variadic function.
Post 27 Mar 2017, 19:51
View user's profile Send private message Reply with quote
system error



Joined: 01 Sep 2013
Posts: 670
system error 27 Mar 2017, 19:56
Furs wrote:
The 64-bit calling convention (for some reason referred as "ABI") is a pathetic trash design to begin with, especially the one by Microsoft.
-- snip--

/end rant sorry Razz


Alignment is a processor thingy. Not OS. 64-bit calling conventions is tailored to suit such CPU requirement.
Post 27 Mar 2017, 19:56
View user's profile Send private message Reply with quote
system error



Joined: 01 Sep 2013
Posts: 670
system error 27 Mar 2017, 20:02
@CodeHeretic

If u want to start off with 64-bit programing, go ahead. You can't go wrong with it. Don't let other people scare you.

It's YOUR PROCESSOR, not theirs.
Post 27 Mar 2017, 20:02
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 27 Mar 2017, 20:27
Thank you for correcting that error and explaining.

So I don't move the hello string into a register. I just push it in the stack?

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



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 27 Mar 2017, 20:31
system error wrote:

Code:
start:
    push Hello
    call [printf]
    add esp,4
    push 0
    call [ExitProcess]
    



This code shows the same results as:

Code:
start: 
    push Hello 
    call [printf]  
    push 0 
    call [ExitProcess]
    


What am I not understanding?

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



Joined: 01 Sep 2013
Posts: 670
system error 27 Mar 2017, 20:43
C0deHer3tic wrote:
Thank you for correcting that error and explaining.

So I don't move the hello string into a register. I just push it in the stack?


In 32-bit Win/C API 'calling convention', yes. You pushed the address on to the stack. Pass by reference.

But you should aware that processor knows no calling convention. What you're dealing with here is an abstraction layer of the OS and / or the library. Don't form a hardened opinion and habit in your early learning phase with the idea that OS = CPU = library. You can see things more clearly if you can separate them.

Most people seems reluctant to move from 32-bit to 64-bit world because they've been brainwashed that if it has no "push" or StdHandle in it, then it's not assembly programming. If u understand the CPU clearly, then it doesn't matter what calling conventions or OS you're dealing with. You can handle them like a boss, be it Windows or Linux.
Post 27 Mar 2017, 20:43
View user's profile Send private message Reply with quote
system error



Joined: 01 Sep 2013
Posts: 670
system error 27 Mar 2017, 20:48
C0deHer3tic wrote:
system error wrote:

Code:
start:
    push Hello
    call [printf]
    add esp,4
    push 0
    call [ExitProcess]
    



This code shows the same results as:

Code:
start: 
    push Hello 
    call [printf]  
    push 0 
    call [ExitProcess]
    


What am I not understanding?


Because it's a short program and the effect of not restoring the ESP correctly is minimal. Try a longer program and it will crash because some other APIs depend on the correct ESP to be restored by previous users. ESP is a shared resource.

Try that in GCC, and it will throw segfault almost immediately.
Post 27 Mar 2017, 20:48
View user's profile Send private message Reply with quote
C0deHer3tic



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 27 Mar 2017, 21:21
Thank you for explaining the reasoning. Although I must ask, why add 4 to esp? Why not 5, 3, or 32?

And here is a program I just made and is not working properly.

Code:


entry start

include 'win32a.inc'

Hello db 'Hello World! The number is %d.',0

subtract:
        sub ax,2
        push eax
        push Hello
        call [printf]
        add esp,4
        push 0
        call [ExitProcess]


start:
    mov eax, 4
    add eax,6
    push eax
    push Hello 
    call [printf]
    add esp,4
    call subtract




section '.idata' import data readable
 
library kernel32, 'kernel32.dll', \
        msvcrt,'msvcrt.dll'

import kernel32, \
       ExitProcess,'ExitProcess'
 
import  msvcrt, \
        printf, 'printf'    

    


It is supposed to add 4 to 6 and print "Hello World! The number is 10.

Then I wanted it to subtract 2 from 10, and then print the result.

It prints either 28,29, or 27.

I must not be understanding this like I thought..... Rolling Eyes

I would appreciate not the correct answer, but a means of finding out for myself or a guide to helping me.

Learning C was so much simpler....haha. Laughing

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



Joined: 25 Mar 2017
Posts: 49
C0deHer3tic 27 Mar 2017, 21:53
This code works:

Code:

format PE console

entry start

include 'win32a.inc'

Hello db 'Hello World! The number is %d.',0

subtract:
        sub eax,1
        push eax
        push Hello
        call [printf]
        add esp,4
        push 0
        call [ExitProcess]


start:
    mov eax, 4
    add eax,6
    push eax
   ; push Hello
   ; call [printf]
   ; add esp,4
    call subtract




section '.idata' import data readable
 
library kernel32, 'kernel32.dll', \
        msvcrt,'msvcrt.dll'

import kernel32, \
       ExitProcess,'ExitProcess'
 
import  msvcrt, \
        printf, 'printf'        

    


Why can't I print out them both?

_________________
- Just because something is taught one way, does not mean there is not a different way, possibly more efficient. -
Post 27 Mar 2017, 21:53
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic This topic is locked: you cannot edit posts or make replies.

Jump to:  
Goto page 1, 2, 3, 4, 5, 6  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 © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.