News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Hello from an absolute beginner

Started by brazer, January 15, 2023, 04:40:09 AM

Previous topic - Next topic

NoCforMe

Quote from: brazer on January 15, 2023, 11:07:57 PM
To my current knowledge the only difference is address size, use of segment registers [...]

Forget segment registers; that went out the window with 16-bit DOS programming on the 8088. No need to touch them, so long as you're not attempting to write kernel code.
Assembly language programming should be fun. That's why I do it.

brazer

Appreciate new replies!

Btw. guys, I wonder how do you format your source files?

Do you do it all yourself by hand?
Do you have some custom made formatters that suit your taste?
And are there some general conventions or online guidelines on how source files should be formatted?

Because I couldn't find any for MASM, I'm currently writing a very simple formatter which I plan to execute on demand from vscode,
because copying sample code from books results in pretty messed up code and adjusting each line is not very pleasant job.
ASM Formatter
https://github.com/metablaster/ASM-Formatter

jj2007

Quote from: brazer on January 16, 2023, 09:31:48 AMhow do you format your source files?

What exactly do you mean? How would you format this little proc?

Format-wise, I see some elements:
- "uses" instead of manually preserving esi and edi
- pString and sLen, instead of pString:DWORD and sLen:DWORD (i.e. using the defaults)
- name of proc in column zero, same for Locals
- afterwards, 2 spaces for the first level, one or more tabs for the next .if etc levels
- mov eax, 123 (not mov eax,   123 or mov eax,123)
- comments separated from code by tabs (you can easily relaunch the tabs vs spaces war here...)

Is that what you mean with formatting?

AdjDlg proc uses esi edi pString, sLen
LOCAL xPosC, yPosC, rc:RECT
  ClearLocals
  invoke GetClientRect, hWnd, addr rc
  .if eax
push edi
mov edi, offset wp ; enable wpos
m2m wpos.wpl.iLength, WINDOWPLACEMENT ; needed once for *etWindowPlacement
mrm wpos.ReHeight, rc.bottom
mrm xPosC, rc.right
mov eax, tbw
movi edx, 511 ; limit tbw to 511
.if eax>edx
xchg eax, edx
mov tbw, edx
.endif
  .endif
  ret
AdjDlg endp

NoCforMe

I don't want to get into a fight with my friend JJ here, but I must point out that what he presented here is NOT standard assembly language coding; it's done with a tool that he has constructed called MasmBasic which combines elements of BASIC programming with "pure" assembly language. It's a great tool, but one that I've never used. Just so you know, because some of the constructs here simply won't work with standard MASM (the Micro$oft assembler, ml).

Other than that, this is one possible way to format assembly-language source code. There are others. I prefer a much more straightforward look, one that doesn't involve C-like indentation and the use of macros as seen here. But to each his own.

Here's a small example of how I like to format my code:


;====================================================================
; FillMem (where, howMuch, what)
;====================================================================

FillMem PROC where:DWORD, howMuch:DWORD, what:DWORD

MOV ECX, howMuch
JECXZ exit99

PUSH EDI
MOV EAX, what
MOV EDI, where
REP STOSB
POP EDI

exit99: RET

FillMem ENDP


I prefer the explicit PUSH/POP sequence rather than letting the assembler bracket the PROC with "USES", so I know where that pushing and popping is taking place.
Assembly language programming should be fun. That's why I do it.

TimoVJL

Quote from: NoCforMe on January 16, 2023, 07:09:16 AM
Forget segment registers;
The FS and GS segments are still functional in 64-bit mode.
May the source be with you

NoCforMe

Well, do you ever need to manipulate them?
Assembly language programming should be fun. That's why I do it.

hutch--

brazer,

One thing you do need is a decent editor, one with auto indent and matching tab replacement so your formatting is consistent. The trick with writing assembler code is to lay it out so you can read it next time. Long ago I have written auto formatters (mainly for the practice) but when you are serious, you format manually, you get accuracy and readability and with practice, you get fast enough.

Code formatting is very much a matter of personal taste but making it readable (to you) is important if you have to come back to code you have written some years ago.

Now commenting is also a matter of personal taste, over do it and your code turns into a cluttered mess, under do it and you suffer the WTF problem.

jj2007

Quote from: NoCforMe on January 16, 2023, 10:55:11 AM
I don't want to get into a fight with my friend JJ here, but I must point out that what he presented here is NOT standard assembly language coding; it's done with a tool that he has constructed called MasmBasic which combines elements of BASIC programming with "pure" assembly language.

David, you are becoming paranoid: with the exception of ClearLocals (my apologies), there is not a trace of MasmBasic in what I posted. There are plenty of sources in \Masm32\examples\*.asm that are formatted similar to my example. In many of them, you will find someproc uses esi edi arg. Get used to it, it saves unnecessary typing and lets you concentrate on good, coherent code.

As to "elements of BASIC programming", almost 100 of the Masm32 SDK examples use the print macro (for example, there are many others). If you hate Basic so much, take on a fight with Hutch, it's his macro.

NoCforMe

Sorry, my bad. I saw a bunch of what are obviously macros (ClearLocals, m2m, mrm), plus some undeclared stuff (wp, wpos) that I assumed was from MasmBasic. Nevermind.

Still, to me it illustrates why you might not want to use macros. (I don't use them at all.) There are so many of them, it's easy to get name collisions if you're not familiar with them, and they sometimes make it less obvious what's going on, since there's now a lot of stuff happening "behind the scenes". Just my 2ยข worth.
Assembly language programming should be fun. That's why I do it.

jj2007

mov edi, offset wp ; enable wpos
m2m wpos.wpl.iLength, WINDOWPLACEMENT ; needed once for *etWindowPlacement
mrm wpos.ReHeight, rc.bottom


m2m and mrm are Masm32 SDK macros, wp is obviously a standard global variable, wpos is obviously a standard global structure. I suppose using e.g. mov wc.hIcon, rv(LoadIcon, eax, IDI_APPLICATION) would also be an evil offense to the bare metal religion?

push 32512
push eax
call LoadIcon
mov wc[24], eax


Much "purer", right?

hutch--

I do understand why some folks shy away from macros but masm in both 32 and 64 bit are MACRO ASSEMBLERS and its part of their design. Documentation helps (if you bother to read it) but there is much hack code that you need to get through with the least amount of brain utilised so you can use your brain resources on the stuff that matters, mnemonic coding in algorithms where speed matters.

jj2007

Quote from: hutch-- on January 16, 2023, 01:34:53 PM
I do understand why some folks shy away from macros but masm in both 32 and 64 bit are MACRO ASSEMBLERS and its part of their design.

Amen :thumbsup:


Quote from: NoCforMe on January 16, 2023, 01:24:31 PMStill, to me it illustrates why you might not want to use macros. (I don't use them at all.)

proc at the beginning and ret at the end of a procedure are macros, you shouldn't use them.

Real MenTM use formatting such as:
mov eax, 123
mov [Myvar], eax
cmp eax, 0
je EaxWasZero
nop
EaxWasZero:


Softies from the macro brigade prefer...
mov eax, 123
mov Myvar, eax
.if eax
nop
.endif

... because they have more important things to do than praying to the Bare Metal God.

NoCforMe

Well, since we're into it now, JJ, might as well take the next step.

1. I'm not a "bare metal" programmer and don't care for that style at all. And yes, I do use a few macros: RET, because I don't want my brain to have to keep track of how many parms are on the stack and have to put a "LEAVE" in every time, and INVOKE, since push-push-call is a pain in the ass.

2. You stated out that "wp is obviously a standard global variable, wpos is obviously a standard global structure". Not obvious to me at all. Here I'll inject a bit of advice to the OP, if I may: I have a system for identifying variables. Much simpler than "Hungarian notation", which is also a pain in the ass in my view. I have 3 types of identifiers:

  • Global variables always start with uppercase: MasterControlTable
  • Local variables (i.e., on the stack) always start with lowercase: fileHandle
  • Constants start with a dollar sign: $mainWindowWidth
Works for me; reduces confusion as to where variables are. Even if you don't like this specific scheme, I suggest coming up with some kind of naming scheme that makes sense to you. As we all know, one of the big problems with programs, especially when they get big, is "name management". Please don't use indecipherable 6-character FORTRAN names!

Oh, and my last piece of advice: Use comments. Lots of them. They're not for other people, though they can be very helpful to them; they're for you. For when you come back to your code 6 months or a year later and try to figure out just what the hell you were trying to do.
Assembly language programming should be fun. That's why I do it.

hutch--

 :biggrin:

You guys are too sophisticated for me, while I regularly use descriptive naming for variables, the only method I use is simple prefixes, "h" for handles (in most instances), "p" for pointers in most instances, I don't distinguish between LOCAL and GLOBAL variables as I use name separation between them and draw the distinction on the basis of required scope.

NoCforMe

"h" and "p" are good. My point was that it's good to have some kind of system. Nothing like looking at your own code and trying to sort out dozens of names
Assembly language programming should be fun. That's why I do it.