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

brazer

Quote from: jj2007 on January 16, 2023, 10:34:14 AM
What exactly do you mean? How would you format this little proc?

I see, no guidelines but personal taste, I may change my mind with time but for now I would indent everything except procedure labels and line comments,
and keep inline comments on equal distance and a bit of space and sectioning here and there, therefore something like this:


; Comment at the start of line

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
Certainly like your style

Quote from: hutch-- on January 16, 2023, 12:35:48 PM
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.

I did suspect it's personal taste because not much can be found on the net, I was able to find only one lengthy resource:
http://www.sourceformat.com/coding-standard-asm-style.htm

It seems the biggest dilemma as to what to indent is symbols, macros, directives etc. since there is many of these and anything except mnemonics and comments.
But OK, if it's personal preference then it better stays so.

I'm pretty sure a lot of stuff is personal perference not just coding style, editors, debuggers and what not, easy to spark a fight over these things hehe :biggrin:
ASM Formatter
https://github.com/metablaster/ASM-Formatter

NoCforMe

Yes, editors (and the other stuff you mentioned) are definitely personal preferences. Not trying to push it, but I just posted a new version of my editor which I've been using for the last couple months to edit assembly-language source. You might try it out. There are, of course, others here; there's Qeditor (by Hutch) in the MASM32 package, and I think others as well. Anyhow, if you feel like it, give mine a spin. I can tell you that it is stable and won't crash, even if it isn't 100% finished. (I call it 90% done with 90% to go.)

Something else: you heard mention of MasmBasic here. This is JJ's creation, truly a labor of love. It's a complete integrated environment, I guess you could call it an IDE, for assembly programming that includes a ton of useful stuff, including a RichEdit editor, debugging tools, lots of stuff. I don't use it myself because it's too much of a "toaster" for me (stick in a slice of bread and out pops the toast). But that's just me; I like to "roll my own". But lots of folks really like using it. It's included in the MASM32 download, and if you have any questions JJ can answer them, of course.

Lots of ways you can go here ...
Assembly language programming should be fun. That's why I do it.

daydreamer

There is also different taste in assembler, ml or uasm
Good thing to use a debugger to single-step thru code to get better understanding how it works
When fpu registers move up/downposition, you can use many fp registers and correct after run debugger to correct st0-st7
SSE packed compares that produces masks 0 or 0ffffh
Understand flags
For me any text editor can be used to write code,even on my Android tablets
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

jj2007

Quote from: brazer on January 16, 2023, 03:51:07 PM
; Comment at the start of line

AdjDlg proc uses esi edi pString, sLen

LOCAL xPosC, yPosC, rc:RECT
ClearLocals
invoke GetClientRect, hWnd, addr rc

.if eax
push edi
.endif

ret
AdjDlg endp

My version:
AdjDlg proc uses esi edi pString, sLen  ; Comment at the start of proc
LOCAL xPosC, yPosC, rc:RECT
  ClearLocals
  invoke GetClientRect, hWnd, addr rc
  .if eax
push edi
  .endif
  ret
AdjDlg endp


Assembly is a "vertical" language: many short instructions. No uppercase stuff unless it's Windows constants.
My procedures are often more than 40 lines long, so inserting empty lines means I see less lines - no good. My "main thread" starts in column 2, every .if or .Repeat adds a tab. When you reach level 5 or 7, it becomes important :biggrin:

Again, that's mostly personal preference - but there also merely technical considerations:
- all my procs have their names in column 0 and their endp, too
- all my macros have their names in column 0 and their endm, too

The reason is a function of my editor that allows me to select proc, then right-click a popup and choose "Select proc or macro". The editor looks for <CrLf>somename proc, then <CrLf>somename endp, and voilà, you can press Ctrl X to move safely an entire 500-line procedure to another place or file.

As others have said, use whatever you like but be coherent. Many of us like automating such stuff, and self-inflicted rules help a lot ;-)

Quote from: NoCforMe on January 16, 2023, 05:24:20 PMMasmBasic ... is included in the MASM32 download

Thanks, David. MasmBasic and its editor, RichMasm, are not included in the Masm32 SDK, there are a separate download and a dedicated sub-forum, but they build on the Masm32 SDK and are fully compatible with it. Installation details are here, a glimpse at the additional functions here.

hutch--

Here is a sample of my own personal style for pure mnemonic code. Pure 64 bit with /LARGEADDRESSAWARE option.

; «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»

NOSTACKFRAME

char_fill proc

  ; rcx = memory address
  ; rdx = byte count
  ; r8  = char

    sub rcx, 1
  @@:
    add rcx, 1
    mov BYTE PTR [rcx], r8b
    sub rdx, 1
    jnz @B

    add rcx, 1
    mov BYTE PTR [rcx], 0       ; zero terminate fill

    ret

char_fill endp

STACKFRAME

; «»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»«»

brazer

Quote from: NoCforMe on January 16, 2023, 05:24:20 PM
Yes, editors (and the other stuff you mentioned) are definitely personal preferences. Not trying to push it, but I just posted a new version of my editor which I've been using for the last couple months to edit assembly-language source. You might try it out. There are, of course, others here; there's Qeditor (by Hutch) in the MASM32 package, and I think others as well.

I've run it and clicked around, you've surely put a lot of time crafting it, good job!, I also looked at screenshots of others here
at first glance there are benefits over vscode like toolbar buttons and easy to access snippets in your editor, it certainly feels more close to an IDE than just editor.

However I'm really used to vscode and have already spent days configuring it for asm and launching external debugger.

Quote from: daydreamer on January 16, 2023, 07:24:55 PM
Good thing to use a debugger to single-step thru code to get better understanding how it works
Certainly agree, debugger is probably our best friend, I use WinDbg Preview mainly because it allows docking windows to my liking and because of good dark theme,
it's also launchable from command line with customized setup which is very useful for integration with vscode.
ASM Formatter
https://github.com/metablaster/ASM-Formatter

NoCforMe

Hopefully some useful info for you here. This regards the "Sacred Registers".

In C, you're insulated from this, but when you start writing assembly language, there are some "gotchas" you need to be aware of. One of them is how certain registers need to be handled. (This post applies to 32-bit programming; 64-bit has similar but different register usages.)

Review: the X86 has 4 "general-purpose" registers, EAX, EBX, ECX, EDX, plus some specialized ones: ESI, EDI, ESP, EBP. (I don't include the instruction pointer, EIP, since this is only implicitly manipulated by the programmer, through CALL or JMP.) 3 of the 4 GP registers are considered "scratch", meaning you can change them at will without regard to saving them, unless you need them for some use in your code. That means that you cannot expect these registers to be preserved across any subroutine calls.

The exception is EBX, which is one of the Sacred Registers. This has 2 consequences:

  • You must save and restore EBX if you use it in your code
  • You can expect EBX to be preserved across any function call, including all the Win32 calls
So if you need EBX for some reason in your code, you need to do something like this:


PUSH EBX ;Save sacred register
MOV EBX, EAX
SHL EBX, 1

... ;Do some more stuff

POP ;Restore sacred reg.


(or if this code is inside a PROC, you can add USES EBX to the proc declaration so the assembler will PUSH and POP it for you)

If you have some code where you need to make repeated references to some piece of data, a structure or other entity, you can set EBX to that item and use it across any number of function calls, like so:


LOCAL aStruct:SOME_STRUCT

PUSH EBX ;Save the sacred register

LEA EBX, aStruct ;Point to the structure
MOV [EBX].SOME_STRUCT.aMember1, $someValue
MOV [EBX].SOME_STRUCT.aMember2, $someOtherValue

INVOKE <some Win32 API function>

; EBX still points to our structure:
MOV [EBX].SOME_STRUCT.aMember3, $yetAnotherValue1
MOV [EBX].SOME_STRUCT.aMember4, $yetAnotherValue2

INVOKE <another Win32 API function>

POP EBX ;Restore sacred reg.
RET


Again, just be sure to preserve the original value of this register.

The other 2 sacred registers are ESI and EDI. I'll cover these in the next post about the string instructions. Like EBX, if you use these registers, be sure to save and restore them.
Assembly language programming should be fun. That's why I do it.

NoCforMe

The X86 processors have a very handy set of instructions known as "string instructions". These are designed to easily and quickly load, store and compare arrays of memory data. They were designed for use with text (ASCII data), but they work on any kind of data; they're blissfully unaware of what kind of bytes are being transferred or compared.

The instructions are:

  • LODSx:   Load data from [ESI] into AL/AX/EAX
  • STOSx:   Store data @ [EDI] from AL/AX/EAX
  • MOVSx:   Move data from [ESI] to [EDI]
  • SCASx:   Compare data @ [EDI] to AL/AX/EAX
  • CMPSx:   Compare data @ [ESI] to [EDI]
where "x" is B for byte, W for word or D for doubleword.

There's also a REP prefix for STOSx and MOVSx which repeats the operation the value in the ECX register times. REP STOSB will store AL starting at [EDI] ECX times. These instructions automatically increment (or decrement, see below) the index register being used, ESI, EDI, or both.

The SCASx and CMPSx instructions have optional prefixes: REPNE repeats the operation until the result of the comparison is "not equal", while REPE repeats while the result is "equal". (The alternate spellings, REPNZ and REPZ are just synonyms.) REPNE SCASB is very useful for searching for a byte value in an array; I use it all the time in parsing.

Like EBX, ESI and EDI are Sacred Registers, so you must preserve them if you use them (and you can expect their values to be preserved across any function calls).

So let's say you want to make a copy of a multibyte structure:

LOCAL srcRect:RECT, destRect:RECT

PUSH ESI ;Save the sacred registers
PUSH EDI
LEA ESI, srcRect
LEA EDI, destRect
MOV ECX, SIZEOF RECT
REP MOVSB
POP EDI
POP ESI


(or include USES ESI EDI in your PROC declaraction)

* Gotcha: I mentioned that the index registers auto-increment; they can also auto-decrement. This depends on the setting of the direction flag. Normally this flag is set to its default, which is auto-increment. If you use the STD ("set direction") instruction, the instructions reverse and auto-decrement. (You can restore the default with CLD.) I have never, ever found the need to mess with this flag, so my advice is to stay away from it. (If you're a paranoid programmer you can use CLD inside a critical routine, but again, I've never had the need to do this.)
Assembly language programming should be fun. That's why I do it.

brazer

NoCforMe,

Thank you this is useful info, I'm already aware of registers that need to be "preserved", including r12-r15 and xmm6-xmm15 in addition to those you mentioned.
But the rest is all new new stuff to me for which I'll come back to recall it.

I do however have some more "philosophical" questions regarding register names...
From what I gathered so far most of the registers names have abbreviations "encoded" in them ex:

  - RAX (accumulator register)
  - RBX (base register)
  - RCX (count register)
  - RDX (data register)

- Pointer registers

  - RIP (Instruction Pointer)
  - RSP (Stack Pointer)
  - RBP (Base Pointer)

- Index registers

  - RSI (Source Index)
  - RDI (Destination Index)

Knowing this it's easy to associate, remember and know what's the purpose of certain registers,
however from what I see, ex. from your examples, this is not written in stone.

ESI and EDI which are supposed to be "index registers" aren't always that? it may be used for what ever at least so it seems from your example,
I assume this applies to all other registers above and probably few others, so my question then is, what's the purpose of abbreviations if registers can be used for anything you like?

Excluding ofc. RSP, RIP which can't, but at least abbreviation for those serves their true purpose.
ASM Formatter
https://github.com/metablaster/ASM-Formatter

NoCforMe

    Quote from: brazer on January 17, 2023, 02:06:00 PM
    I do however have some more "philosophical" questions regarding register names...
    From what I gathered so far most of the registers names have abbreviations "encoded" in them ex:

      - RAX (accumulator register)
      - RBX (base register)
      - RCX (count register)
      - RDX (data register)

    I was going to mention that: the registers on the first of this family (8086/8088) had AX, BX, CX and DX as "general-purpose" registers, except that they weren't really:

    • AX: Yes, "accumulator", target of string load/store, multiplication and division
    • BX: "Base": along with SI & DI the only registers you could use to reference memory and also the base register for the XLAT instruction
    • CX: "Count": counter for LOOP and for ops with REP prefix
    • DX: "Data" register, used to hold index of I/O port for IN & OUT
    Those names are now just historical curiosities. Most of those attachments are no longer true, except that EAX is still the dividend (low word) and the quotient for DIV and the product (low word) for MUL, and still the target of those string instructions. ECX is still used as a counter for string instructions and LOOP. All of them can be used for memory references (along with ESI, EDI, ESP and EBP). Nothing special about using ESI & EDI, so long as you save and restore them.

    BTW, the rule of saving the "sacred registers" has nothing at all to do with the processor; it couldn't care less what you do with those registers. It's simply a convention used by well-behaved programs under Windows (and also *nix?).

    Anything you posted above about 64-bit registers I can't comment on, as I'm not familiar with that scheme. What you wrote looks right, though.


    [/list]
    Assembly language programming should be fun. That's why I do it.

    jj2007

    Quote from: NoCforMe on January 17, 2023, 03:22:36 PMThose names are now just historical curiosities.

    As you write immediately after, these registers are still specialised for certain tasks (xlat, lods*, div). However, you can use them all as general purpose registers, with minor limitations: you can't access the bytes of esi and edi.

    brazer

    Btw. you guys feel free to call me a maniac, even though most of you suggested me to format my sources by hand I just couldn't resist to automate this process,
    because as I copy samples from PDF's it really get's unformatted and difficult to read sometimes.

    Didn't sleep well until I made it which for now at least let's me copy and format sample code from the book without having to adjust each line, it's annoying as hell.

    I've put it on public display and updated my signature below, if nothing else this signature is more appropriate for forums than the previous one since it's at least a little related to assembly lol  :smiley:
    ASM Formatter
    https://github.com/metablaster/ASM-Formatter

    jj2007

    Quote from: brazer on January 17, 2023, 08:38:41 PM
    Btw. you guys feel free to call me a maniac

    Welcome in the club :thup:

    I'd like to test your tool, but 29 files in the asmformat folder are a bit scary, and my C++ installation is broken thanks to the infamous clean temp directory of old il files bug. Can you post the binaries, Win7 compatible if possible?

    Quote from: brazer on January 17, 2023, 08:38:41 PMsample code from the book

    There are many good code samples in \Masm32\examples, don't miss them. Simple but very clear.

    Btw how do you extract the code from a pdf? Sometimes I use AbleWord for that, perhaps you have a better one?

    daydreamer

    Historical ax,bx,cx,dx,si,Di, BP, sp registers in 16bit real mode,put restrictions used in indirect addressing, but in 32bit freely mix 2 of these registers
    Bx and BP = base registers,one of them combined with either si or di = index registers +scale register 2x,4x,8x
    Mov ax,[bx+si+adress]
    Philosophical on RIP register, might be a hint of RIP of 32 bit is coming?  :tongue: :greenclp:


    my none asm creations
    https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
    I am an Invoker
    "An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
    Like SIMD coding

    brazer

    Quote from: jj2007 on January 17, 2023, 08:49:34 PM
    I'd like to test your tool, but 29 files in the asmformat folder are a bit scary, and my C++ installation is broken thanks to the infamous clean temp directory of old il files bug. Can you post the binaries, Win7 compatible if possible?

    Thank you for interest, those are all small sources mostly error handling and boiler plate code which I plan to use, I've compiled executables including for windows 7 and VC++ redistributables, however VC++ redist fails to install on my Win7 virtual machine probably because system is out of date but it may work in your case.
    They are here
    Looking forward for your opinion!

    Quote from: jj2007 on January 17, 2023, 08:49:34 PM
    There are many good code samples in \Masm32\examples, don't miss them. Simple but very clear.

    Btw how do you extract the code from a pdf? Sometimes I use AbleWord for that, perhaps you have a better one?
    I'll take a look at samples in \Masm32, but those in the book are easy to understand for a beginner, since every sample is explained in detail how it works.

    I'm using normal copy\paste out of the pdf, but there are always some spaces at every start of line, and everything is on same column and sometimes on different columns,
    blank lines are not preserved and it's not always the same or as presented in the book, which makes harder to focus on sections of code, but this is now solved.

    Quote from: daydreamer on January 17, 2023, 10:40:22 PM
    Historical ax,bx,cx,dx,si,Di, BP, sp registers in 16bit real mode,put restrictions used in indirect addressing, but in 32bit freely mix 2 of these registers
    Bx and BP = base registers,one of them combined with either si or di = index registers +scale register 2x,4x,8x
    Mov ax,[bx+si+adress]
    Philosophical on RIP register, might be a hint of RIP of 32 bit is coming?  :tongue: :greenclp:
    OK so I don't need to bother then if it's all just historical reasons, but in any case knowing the "long" names of registers makes it easier to remember and differentiate them so that's something,
    since there are so many of them to remember them all at once.

    Hah, I like your joke about RIP register lol  :rofl:
    I don't know if and when will 32 bit systems go out of scope, likely not anytime soon yet, there is still a bunch of devices running on 32 bit CPU's.

    What criteria would there have to be to drop 32 bit OS support? hardware manufacturers perhaps? probably more likely than OS vendors.
    ASM Formatter
    https://github.com/metablaster/ASM-Formatter