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 |
|
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. I just realized there's no comments. |
|||
26 Mar 2017, 00:32 |
|
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.
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? 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. _________________ - Just because something is taught one way, does not mean there is not a different way, possibly more efficient. - |
|||
26 Mar 2017, 02:39 |
|
Trinitek 26 Mar 2017, 04:20
You might not need printf, but some sort of output would be nice, no? Debuggers hurt the eyes.
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 |
|||
26 Mar 2017, 04:20 |
|
C0deHer3tic 26 Mar 2017, 04:46
Thank you for the time to comment your code!
I am still curious for a beginner course to assembly language, but that was helpful. _________________ - Just because something is taught one way, does not mean there is not a different way, possibly more efficient. - |
|||
26 Mar 2017, 04:46 |
|
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.
|
|||
26 Mar 2017, 22:08 |
|
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. |
|||
27 Mar 2017, 07:06 |
|
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. |
|||
27 Mar 2017, 08:03 |
|
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 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 |
|||
27 Mar 2017, 17:06 |
|
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 Φ☼ Sincerely, C0deHer3tic _________________ - Just because something is taught one way, does not mean there is not a different way, possibly more efficient. - |
|||
27 Mar 2017, 19:33 |
|
Trinitek 27 Mar 2017, 19:46
Parameters go on the stack in the 32-bit stdcall convention. Like so...
Code: start: push Hello call [printf] push 0 call [ExitProcess] |
|||
27 Mar 2017, 19:46 |
|
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. |
|||
27 Mar 2017, 19:51 |
|
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. Alignment is a processor thingy. Not OS. 64-bit calling conventions is tailored to suit such CPU requirement. |
|||
27 Mar 2017, 19:56 |
|
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. |
|||
27 Mar 2017, 20:02 |
|
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. - |
|||
27 Mar 2017, 20:27 |
|
C0deHer3tic 27 Mar 2017, 20:31
system error wrote:
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. - |
|||
27 Mar 2017, 20:31 |
|
system error 27 Mar 2017, 20:43
C0deHer3tic wrote: Thank you for correcting that error and explaining. 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. |
|||
27 Mar 2017, 20:43 |
|
system error 27 Mar 2017, 20:48
C0deHer3tic wrote:
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. |
|||
27 Mar 2017, 20:48 |
|
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..... 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. _________________ - Just because something is taught one way, does not mean there is not a different way, possibly more efficient. - |
|||
27 Mar 2017, 21:21 |
|
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. - |
|||
27 Mar 2017, 21:53 |
|
Goto page 1, 2, 3, 4, 5, 6 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.