The MASM Forum

General => The Campus => Topic started by: RedSkeleton007 on February 05, 2016, 06:45:02 PM

Title: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 05, 2016, 06:45:02 PM
I no longer care about using Irvine or Visual Studio. Screw Visual Studio. KILL Visual Studio!

That being said, lets begin :bgrin:

I'm an absolute beginner. My first priority is learning how to properly use basic op-codes. That being said, hutch--, I appreciate your neat print out code here:  https://masm32.com/board/index.php?msg=54890
But it's a little too advanced for me right now. Visual Studio did such a nice job displaying everything by calling Dumpregs, and I was expecting something similar to happen by following dedndave's instruction here:
Quote from: dedndave on February 05, 2016, 06:19:25 AMdowload OllyDbg - as i recall, installation is merely a matter of creating a folder and placing the program in it

you want to make Olly the "default just-in-time" handler
if you open Olly, there is an Options menu
under Debugging, Just-in-time - Set OllyDbg button
it takes care of it for you, and saves previous settings if you want to reverse it

now, any program that generates an exception will cause Olly to pop up
we generally insert
    int     3into the code where we want execution to generate an exception

And I added the int 3 into the MyTest.asm file:

include \masm32\include\masm32rt.inc

.data
MyArray dd 25, 18, 23, 17, 9, 2, 6
HelloW$ db "Hello World", 0

.code
start:
  xor ebx, ebx ; set two non-volatile
  xor esi, esi ; registers to zero
  .Repeat
add esi, MyArray[4*ebx]
inc ebx
  .Until ebx>=lengthof MyArray
  MsgBox 0, cat$(str$(esi), " is the sum"), offset HelloW$, MB_OK

int 3
  exit

end start
But none of Olly's features happened like he promised. Any suggestions?

Fixed link above, originally it opened a "quote" editor window.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: GoneFishing on February 05, 2016, 07:23:32 PM
I'd recommend you to use VKDEBUG .
QEDITOR -> Help -> vkDebug
Read it .
All you need to start using it is :

include  \masm32\include\debug.inc
includelib \masm32\lib\debug.lib

Now you may want to find out which function dumps the contents of CPU to DbgWin  and try it .
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on February 05, 2016, 07:56:46 PM
Quote from: GoneFishing on February 05, 2016, 07:23:32 PMNow you may want to find out which function dumps the contents of CPU to DbgWin  and try it.

deb (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1019) is more powerful*), and easier to use. Anyway, DbgWin commands are described in \Masm32\help\VKDebug.chm

However, Olly would be much more helpful, therefore: What exactly doesn't work with Olly?
- do you have the file \Masm32\OllyDbg\ollydbg.exe ?
- when you start Olly, and open the exe produced with qEditor, what do you see?

Below is a screenshot of Olly. This is what you should see if you followed the instructions.

*) same program using deb:
include \masm32\MasmBasic\MasmBasic.inc
; include \masm32\include\masm32rt.inc

.data
MyArray dd 25, 18, 23, 17, 9, 2, 6
HelloW$ db "Hello World", 0

.code
start:
  xor ebx, ebx ; set two non-volatile
  xor esi, esi ; registers to zero
  .Repeat
deb 4, "adding:  ", MyArray[4*ebx]
add esi, MyArray[4*ebx]
deb 4, "new sum:", esi
inc ebx
  .Until ebx>=lengthof MyArray
  Inkey Str$("The sum is %i", esi), Str$(", and the counter arrived at %i", ebx)
  exit

end start


Output:
adding:         MyArray[4*ebx]  25
new sum:        esi             25
adding:         MyArray[4*ebx]  18
new sum:        esi             43
adding:         MyArray[4*ebx]  23
new sum:        esi             66
adding:         MyArray[4*ebx]  17
new sum:        esi             83
adding:         MyArray[4*ebx]  9
new sum:        esi             92
adding:         MyArray[4*ebx]  2
new sum:        esi             94
adding:         MyArray[4*ebx]  6
new sum:        esi             100
The sum is 100, and the counter arrived at 7

Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on February 05, 2016, 08:04:57 PM
Red,

The trick is not to take on too much in one go, get used to things a bit at a time. The MASM32 library and macro system is there to get you up and going. Once you learn enough you can start to do the fancy stuff. You need to learn the basics of intel mnemonics, the complex addressing mode and the bare minimum of Windows API functions. Just take it a bit at a time and it will all come together. I wrote the 2 simple procedures on register contents so you had a simple and easy to use way of seeing what you registers held. Once you learn the basics you can start on a debugger if you need it but a lot of code can be written before you need to learn a debugger.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on February 05, 2016, 08:23:30 PM
Hutch,

I fully agree that the Masm32 library is the best invention ever after the wheel, but to start learning and understanding assembly, there is nothing simpler than opening an exe in Olly and pressing F8 repeatedly.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on February 06, 2016, 12:10:24 AM
Red,

The trick with the 2 procedures I posted is you don't have to understand them in a hurry, they work as they are by simply calling them. Once you know a bit more you will know what they are doing, both copy all of the registers to some memory based variables, then they are displayed using a couple of different macros, one for console, the other for joining all the results and shown in a message box. Many have tried to start in assembler by trying to learn all of the low level basics but it rarely ever works well as there is so much to start with.

The reason for the MASM32 library and the macro support is because MASM does not have a run time library so one was created to make starting with MASM a lot easier. If you use the runtime library and the macros you will get a lot more code up and running and this will make learning the important stuff like mnemonic coding a lot easier. A lot of API functions are just hack OS code to interact with the OS but direct mnemonic code is where the real action is and its where you get some real speed once you properly understand it.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 06, 2016, 12:41:22 AM
that's a big step in the right direction   :t

you will find that the masm32 package is a much faster way to get serious about writing windows-32 code
however, don't discount Kip Irvine's book, altogether
it does a fair job of explaining data types, registers, and instructions
the problem is to be able to take one of Kip's example programs, and convert it to masm32

to understand this "translation", a little background might be helpful....

in the days of 16-bit DOS code, much of the hardware was accessed through software and hardware interrupts
hardware generated physical interrupts that the 8088 "detected", causing specific code to be executed
for example, when a timer interrupt occured, a timer routine in BIOS was executed to update a clock count

software interrupts were "called" by programs using the INT instruction
in most cases, arguments were passed to the interrupts via registers
so, to open a file, for example, you would load AX, CX, and DS:DX with specific values, then INT 21h (DOS function dispatcher)
    mov     ah,3Ch               ;INT 21h function number to create a file
    mov     cl,<file attributes>
    mov     dx,offset filename   ;assuming that DS points to the proper data segment
    int     21h


if the function is successful, the INT returns with the carry flag cleared
if there is an error, the carry flag is set, and AX holds the error code
for some functions, values were also returned in other registers

that is old stuff that you really don't want or need to learn
but, i wanted you to see how calls were made
program functions were often written to be called in much the same way
Kip Irvine (and several others) wrote books, based on these methods

when the transition to 32-bit windows code was made, Kip adapted his old code to work in the new world
windows was designed with a whole new set of "rules"
however, the code examples in Kip's book don't obey the new rules
and, that is where the problems begin - lol

enough history lesson
to work with windows, you will want to understand parts of the windows ABI (application binary interface)
the ABI describes many things, like how object modules are linked and so on
it also gives a basic set of rules for how operating system functions are called, and how they return information:

rather than passing arguments in registers, they are passed on the stack
EBX, EBP, ESI, and EDI registers are preserved across calls
EAX, ECX, and EDX are volatile (may be destroyed)
EAX is often used to return a status or result (not the carry flag, like DOS)
(if a function requires more space to return results, it is usually passed the address of a data structure to fill in)
the direction flag is normally left cleared (up direction)
if you set it (down direction) for your code, you should clear it when done
many operating system functions require the direction flag to be cleared prior to call

the key is, that we generally write our own functions to behave the same way - to follow the same rules
that way, they are interchangable with OS functions
in cases where the ABI must be observed, our own functions obey the rules
i think it's correct to say that all of Hutch's functions in the masm32 library follow the ABI rules

that having been said, there are ways to take Kip's examples and make them masm32 compatible
when one of Kip's "WriteXxxxx" functions are called, you can generally replace it with the masm32 "print" macro
understand that Kip's routines pass arguments in registers - and that he has a tendancy to preserve most registers across calls
very different from the windows ABI
what you really want to do is to be able to follow his code to learn instructions
then, know how to make it work in the simpler world of masm32 code   :biggrin:
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 07, 2016, 04:54:16 AM
Quote from: jj2007 on February 05, 2016, 07:56:46 PM
However, Olly would be much more helpful, therefore: What exactly doesn't work with Olly?
- do you have the file \Masm32\OllyDbg\ollydbg.exe ?
- when you start Olly, and open the exe produced with qEditor, what do you see?
I didn't realize I needed to open the MASM32-Editor-produced .exe file in Olly. My bad. I also now understand that pressing F8 steps through (debugs) lines of .asm code one line at a time, kind of like Visual Studio's debugger.

But what exactly was the point of dedndave adding int   3 to the code?

Also, I couldn't see the Flag statuses anywhere in Olly when I ran it (see my attached screen shot, and help me find them please).

NOTE: the .asm code that generated the .exe file used by Olly in the attached screen shot is:

include \masm32\include\masm32rt.inc

.data
MyArray dd 25, 18, 23, 17, 9, 2, 6
HelloW$ db "Hello World", 0

.code
start:
  xor ebx, ebx ; set two non-volatile
  xor esi, esi ; registers to zero
  .Repeat
add esi, MyArray[4*ebx]
inc ebx
  .Until ebx>=lengthof MyArray
  MsgBox 0, cat$(str$(esi), " is the sum"), offset HelloW$, MB_OK
  exit

end start


One more thing: can someone please paste the code for a simple .asm template that will output straight to a console window or dialog box automatically when run with MASM32 Editor (instead of outputting a console-dialog-box-hybrid that the code above does)? Thanks again.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 07, 2016, 05:24:58 AM
this should answer 2 of the questions/requests

;###############################################################################################

        INCLUDE    \Masm32\Include\Masm32rt.inc
        .686p
        .MMX
        .XMM

;###############################################################################################

  ;      .DATA

;***********************************************************************************************

  ;      .DATA?

;###############################################################################################

        .CODE

;***********************************************************************************************

main    PROC

        print   "Hello "

        int     3                      ;generate exception to bring up OllyDbg

        print   "World!",13,10
        inkey
        INVOKE  ExitProcess,0

main    ENDP

;###############################################################################################

        END     main
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on February 07, 2016, 05:41:11 AM
Quote from: RedSkeleton007 on February 07, 2016, 04:54:16 AMBut what exactly was the point of dedndave adding int   3 to the code?

Also, I couldn't see the Flag statuses anywhere in Olly when I ran it (see my attached screen shot, and help me find them please).
...
One more thing: can someone please paste the code for a simple .asm template that will output straight to a console window or dialog box automatically when run with MASM32 Editor (instead of outputting a console-dialog-box-hybrid that the code above does)? Thanks again.

- the point of int 3: If you press F9, Olly runs the code until it hits int 3. Useful when your code grows bigger.
- the flags are under the registers in the right panel:
C0
P1
A0
Z1
S0


- template:

include \masm32\include\masm32rt.inc
.code
start:
  nop
  inkey "hello world"
  exit
end start
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 07, 2016, 05:43:45 AM
this is a picture of the Olly window when my little program above is executed
circled in red is the EFL (EFlags) register

notice that Olly came up when the INT 3 was executed
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 09, 2016, 10:45:50 AM
Quote from: dedndave on February 07, 2016, 05:43:45 AM
circled in red is the EFL (EFlags) register
Thanks, but I was looking for Status Flags. Also, why doesn't the number in Olly's EDX register (attached screen shot image) match the prediction comment in my code:

include \masm32\include\masm32rt.inc
.data
val1 WORD 1000h
val2 WORD 2000h
.code
start:

; Demonstrate MOVZX instruction:
    mov bx,0A69Bh
    movzx eax,bx ; EAX = 0000A69Bh
    movzx edx,bl ; EDX = 0000009Bh predicted value
    movzx cx,bl  ; CX = 009Bh
  nop
  ; inkey "hello world"
  ; inkey EDX
  exit
end start

Also, how do you display attached images between text and stuff, inline with posts?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on February 09, 2016, 11:25:37 AM
Quote from: RedSkeleton007 on February 09, 2016, 10:45:50 AMI was looking for Status Flags.
These are the status flags.

QuoteAlso, why doesn't the number in Olly's EDX register (attached screen shot image) match the prediction comment in my code

Because you forgot to hit F8 until you reach the point of your prediction.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 09, 2016, 06:07:05 PM
Ready to have some fun? The questions are in the comments of the following code:

include \masm32\include\masm32rt.inc
.data
val1 WORD 1000h
val2 WORD 2000h
strDuke BYTE "Duke Nukem" ; should be 10 bytes, right?
.code
start:

; Lets find out what inkey can do:
    inkey strDuke ; when run, this statement causes the program to crash. Why?
    inkey "It's time to kick ass and chew bubble gum..."
    mov eax,SIZEOF strDuke

; Lets also try out xchg:
    mov si,val1 ; SI = 1000h
    xchg si,val2 ; SI = 2000h, val2 = 1000h
    mov val1,si ; SI = 2000h
    ; NOTE: SI is from the extended source index register ESI
   
  nop ; what is nop supposed to do?
 
  inkey "and I'm all out of gum."
  exit
end start

Also, in the attached screen shot, despite hitting F8 as many times as Olly let me, the value in register SI (of ESI) stayed the same 00000000. Why?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on February 09, 2016, 06:14:10 PM
Which book are you using? "The Art of Spoon-Feeding"?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on February 09, 2016, 06:50:29 PM
Red,

Why the hell are you working in 16 bit ?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 09, 2016, 09:46:46 PM
inkey strDuke

the inkey macro wants an address
"strDuke" will likely try to use the first 4 bytes of the string as an address
the address is probably invalid, and that causes the crash

try this
inkey offset strDuke
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 09, 2016, 09:50:12 PM
strDuke BYTE "Duke Nukem" ; should be 10 bytes, right?

it is 10 bytes, but you really don't care
and - strings should be null-terminated

strDuke BYTE "Duke Nukem",0 ;11 bytes total

it may be the lack of a null-terminator that causes it to crash
i am not sure how the macro interprets the label without "offset", because i've never used it that way - lol
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 10, 2016, 09:29:49 AM
Quote from: hutch-- on February 09, 2016, 06:50:29 PM
Why the hell are you working in 16 bit ?
If you say that, my best guess is that you're talking about this part:

mov si,val1 ; SI = 1000h
    xchg si,val2 ; SI = 2000h, val2 = 1000h
    mov val1,si ; SI = 2000h
    ; NOTE: SI is from the extended source index register ESI

Since val1 and val2 are only 4 digits, I figured they're 16 bit, and thus could fit into the first 4 LSB portion of the ESI register (or at least, that's my assumption to why the code example in the book shows it that way).
Quote from: dedndave on February 09, 2016, 09:50:12 PM
strDuke BYTE "Duke Nukem" ; should be 10 bytes, right?

it is 10 bytes, but you really don't care
and - strings should be null-terminated

strDuke BYTE "Duke Nukem",0 ;11 bytes total

it may be the lack of a null-terminator that causes it to crash
i am not sure how the macro interprets the label without "offset", because i've never used it that way - lol
Thank you dedndave, that actually does make sense.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 10, 2016, 10:02:48 PM
in 32-bit code, using word registers is generally slower than using full registers
the opcodes for word register instructions include an extra prefix byte to indicate the "non-native" size

byte register instructions still have unique opcodes (just like 16-bit code), so do not require the override byte

many operations are best performed on full-size registers
and, when memory operands are concerned, it is helpful if they are DWORD-aligned
(i.e., the address for a DWORD operand is evenly divisable by 4)
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 24, 2016, 08:43:23 PM
There are 8 general purpose registers:
EAX, EBX, ECX, EDX, ESI, EDI, ESP, and EBP.

Now, are they strictly designated to specific purposes, or does MASM allow me to each register for whatever I want?

Also, I have a few errors and a question in my code:


include \masm32\include\masm32rt.inc
.data
val1 WORD 1000h
val2 WORD 2000h
strDuke BYTE "Duke Nukem",0 ; 11 bytes

.code
start:

; First, lets find out what inkey can do:

    inkey OFFSET strDuke
    inkey "It's time to kick ass and chew bubble gum..."

; Next, lets figure out how to move the amount of bytes in
; our string into a register, so that we can use it to
; observe that information using the displayed registers
; in Olly:
     
    mov edi, SIZEOF strDuke   

; Finally, lets learn how to use the xchg opcode, so that
; val1 and val2 trade values:

    mov eax, val1 ;error: instruction operands must be the same size
    xchg eax, val2 ;error: instruction operands must be the same size
    mov val1, eax ;error: instruction operands must be the same size
   
  nop ; what is nop supposed to do?
 
  inkey "and I'm all out of gum."
  exit
end start


Note that the inkeys worked fine when I ran the program before attempting to add in the xchg stuff.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on February 24, 2016, 08:47:54 PM
Red,

have a look in the masm32 help files, the Intel ABI is explained there and its a lot easier to point you there than repeat it all as a post.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 25, 2016, 12:48:31 AM
the problem is...

the register operand EAX is a DWORD size
the memory operand val1 is a WORD size
they must be the same size (change val1 to a DWORD)

this is true for most instructions
there are a few exceptions, like MOVSX or MOVZX, which convert bytes or words to dwords

ESP is fairly dedicated to the stack
the other 7 can be used in many ways
but, each one has special characteristics
often, these characteristics are due to specific instruction usage
MOVS, MUL, DIV are a few good ones to study

historically:
AX - accumulator
BX - base index address
CX - count
DX - data
SI - source index address
DI - destination index address
BP - base pointer (stack)
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 25, 2016, 06:54:19 PM
Quote from: dedndave on February 10, 2016, 10:02:48 PM
in 32-bit code, using word registers is generally slower than using full registers
the opcodes for word register instructions include an extra prefix byte to indicate the "non-native" size

byte register instructions still have unique opcodes (just like 16-bit code), so do not require the override byte
The override byte? Does the movzx instruction have anything to do with that?

Quote from: dedndave on February 10, 2016, 10:02:48 PM
many operations are best performed on full-size registers
and, when memory operands are concerned, it is helpful if they are DWORD-aligned
(i.e., the address for a DWORD operand is evenly divisable by 4)
It seems my code worked:

include \masm32\include\masm32rt.inc
.data
val1 DWORD 1000h
val2 DWORD 2000h

.code
start:

    mov eax, val1 ; would movzx be necessary here?
    xchg eax, val2
    mov val1, eax
   
  nop ; what is nop supposed to do?
 
  inkey "End of program."
  exit
end start

In Olly, as I hit F8, I saw the EAX register change to 00001000 and 00002000 ;)
I found it odd, though, that I didn't have to use movzx, or transfer 16-bit values into 32-bit registers. I guess something in modern 32-bit MASM puts in the first four unused higher bits for you?

One other thing. In Olly, once I've hit F8 enough times to get to the end of stepping through my program, I don't know how to go back. How do I go back to the first step instead of having to close and reopen Olly, and then reopen my program in Olly?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on February 25, 2016, 07:24:45 PM
Quote from: RedSkeleton007 on February 25, 2016, 06:54:19 PMThe override byte? Does the movzx instruction have anything to do with that?
No.

Quotemov eax, val1 ; would movzx be necessary here?
No. Both eax and val1 are DWORD size, i.e. 4 bytes long.

Quotenop ; what is nop supposed to do?
\Masm32\help\opcodes.chm

QuoteIn Olly, once I've hit F8 enough times to get to the end of stepping through my program, I don't know how to go back. How do I go back to the first step
Ctrl F2.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 26, 2016, 12:59:55 AM
in the original post, i think he had val1 defined as a WORD

so, MOVZX or MOVSX could be used

MOVZX zero-extends the value (all the upper bits are set to 0)
MOVSX sign-extends the value (the upper bits are a copy of bit 15 for words or bit 7 for bytes)

typically, we would just define val1 as a DWORD, though
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 26, 2016, 01:11:11 PM
The book does a shitty job explaining how to exchange array elements :( The following code is untested:

include \masm32\include\masm32rt.inc
.data
val1 DWORD 1234h
val2 DWORD 5678h

temp DWORD ?
temp2 DWORD ?
arrayD DWORD 1000h, 2000h, 3000h, 4000h

.code
start:

    mov eax, [arrayD+8] ; move array element [2] into eax 
    xchg temp, eax ; hopefully, eax is empty for the next mov?
    mov eax, [arrayD+4] ; move array element [1] into eax
    xchg temp2, eax
    mov [arrayD+4], temp
    mov [arrayD+8], temp2

    ;arrayD should now be: 1000h, 3000h, 2000h, 4000h
   
  nop ; no operation to do here.
 
  inkey "End of program."
  exit
end start


Also, inkey has proven to work great for outputting hard-coded statements into the console, but what is the syntax for outputting a specific array element value into the console? Olly is cool, but at my current level, it's just giving me a headache. Is Olly really necessary right now, when I'm struggling to learn just the basic opcodes?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on February 26, 2016, 01:16:17 PM
i troubleshoot most programs without olly - but, it's nice when you need it

if you want to dislpay a value in hex, signed decimal, unsigned decimal...
    print   uhex$(dword ptr [ebx+4])
    print   str$(dwVariableName),13,10
    print   ustr$(eax)


notice i added a carriage return/line feed to one of them
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on February 26, 2016, 01:21:03 PM
Red,

Olly is an OK debugger but you are better to learn the basics first, once you have that under your belt you can add whatever toys you like but the idea is to keep it simple at first or you get tangled in the sheer complexity of trying to do too many things. One of the tricks is to set yourself up a simple test piece and experiment with the instructions and learn how the "complex addressing mode" works, it looks messy but once you understand it, it becomes really easy to use.

Once you are up and going we will show you the FAST way to exchange memory operands, XCHG is both old and slow and can be done a lot quicker, the way its done in fast sort algos.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on February 26, 2016, 01:51:57 PM
Quote from: dedndave on February 26, 2016, 01:16:17 PM
notice i added a carriage return/line feed to one of them
Why? I understand the purpose of null-terminating a string, but what is the purpose of the so-called "carriage return/line feed" instruction?

Quote from: hutch-- on February 26, 2016, 01:21:03 PM
Once you are up and going we will show you the FAST way to exchange memory operands, XCHG is both old and slow and can be done a lot quicker, the way its done in fast sort algos.
So I should completely forget about exchanging values in memory or registers for now?

Also, is this what you mean by complex addressing mode:
http://masm32.com/board/index.php?action=post;quote=254;topic=87.0;last_msg=352 (http://masm32.com/board/index.php?action=post;quote=254;topic=87.0;last_msg=352)
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on February 26, 2016, 02:56:23 PM
The added 13, 10 gives you a carriage return and a line feed. Much the same as pressing the enter key.

RE: exchanges of values, you will do this on a needs basis, have a good look at both the help files in MASM32 AND the examples and tutorials, this is what they were written for, to help folks learning assembler. If you can get the swing of the addressing mode and some practice using instructions, the rest will come with practice.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on March 02, 2016, 05:32:09 PM
And the quest for simple ways of printing register values in the console continues. I've tested the following code (my questions are in the comments as always):

include \masm32\include\masm32rt.inc
.data
val1 DWORD 1000h
val2 DWORD 2000h

.code
start:

    mov eax, val1
    xchg eax, val2
    mov val1, eax ; Wait, if we're removing the value from eax into var1, what's left in eax afterwards?

    ;print   str$(dwVal1),13,10 ; error: INVOKE argument type mismatch (is str$ the problem?)
   
    ;print   ustr$(eax),13,10 ; result was 8192. Why? That can't be in hex.
   
    ;print   str$(eax) ; result was 8192 again. And why did using str$ work this time?

    inkey "We've made it through the operations without errors!" ; yes, we do make it this far and past!
   
  nop ; no operation left to perform

  inkey "End of program."
  exit
end start
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: dedndave on March 02, 2016, 09:48:54 PM
    mov val1, eax ; Wait, if we're removing the value from eax into var1, what's left in eax afterwards?

    ;print   str$(dwVal1),13,10 ; error: INVOKE argument type mismatch (is str$ the problem?)

    ;print   ustr$(eax),13,10 ; result was 8192. Why? That can't be in hex.

    ;print   str$(eax) ; result was 8192 again. And why did using str$ work this time?


1) the source register is unchanged in MOV
2) dwVal1 is not defined - try val1
3) ustr$ converts to unsigned decimal string - 8192 decimal is 2000h
4) i think str$ is the same as ustr$

...and the masm32 package has a bug with regard to ustr$

http://masm32.com/board/index.php?topic=1811.0 (http://masm32.com/board/index.php?topic=1811.0)

i proposed a fix here, with no disagreements - lol

http://masm32.com/board/index.php?topic=1811.msg33372#msg33372 (http://masm32.com/board/index.php?topic=1811.msg33372#msg33372)
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on March 03, 2016, 05:36:44 AM
Quote from: dedndave on March 02, 2016, 09:48:54 PM
2) dwVal1 is not defined - try val1
I still get the same error.

Quote from: dedndave on March 02, 2016, 09:48:54 PM
3) ustr$ converts to unsigned decimal string - 8192 decimal is 2000h
Okay, so how do I get it to print out in hexadecimal? I would prefer to see my output in the same format as my input.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on March 03, 2016, 05:40:38 AM
Quote from: RedSkeleton007 on March 03, 2016, 05:36:44 AMOkay, so how do I get it to print out in hexadecimal?

include \masm32\include\masm32rt.inc
.code
start:
  print hex$(2000h)
  exit
end start

Always at your service 8)
(http://www.youth.ly/wp-content/uploads/2013/11/202191RKERGB75-e1384804892369-620x320.jpg)
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on March 03, 2016, 08:31:39 AM
When I try to print both the value in a register and in a variable at the same time:

include \masm32\include\masm32rt.inc
.data
val1 DWORD 1000h
val2 DWORD 2000h

.code
start:

    mov eax, val1 ; eax should now have 1000h
   
    xchg eax, val2 ; eax should now have 2000h, and val2 should now be 1000h instead of 2000h
   
    mov val1, eax ; val1 should now have 2000h instead of 1000h

    ; val1 and eax should both be 2000h:
    print hex$(val1),13,10 ; result: 00002000
    print hex$(eax),13,10 ; result: 00000002   
   

    inkey "We've made it through the operations without errors!"
   
  nop ; no operation left to perform

  inkey "End of program."
  exit
end start

it prints out two different values. Strangely, the value 00002000 comes out when I only print one of them (from eax or val1). What is going on?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: jj2007 on March 03, 2016, 08:56:08 AM
Quote from: RedSkeleton007 on March 03, 2016, 08:31:39 AM
it prints out two different values. Strangely, the value 00002000 comes out when I only print one of them (from eax or val1). What is going on?

See here (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm), read the part beginning with "Assembly beginners stumble"...
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on March 03, 2016, 01:34:24 PM
Quote from: jj2007 on March 03, 2016, 08:56:08 AM
See here (http://www.webalice.it/jj2006/Masm32_Tips_Tricks_and_Traps.htm), read the part beginning with "Assembly beginners stumble"...

Read. Is it worth my time as a noob to do research on why registers get trashed, or should I just accept that truth and move on?
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on March 03, 2016, 02:35:03 PM
Red,

Its called the "Intel Application Binary Interface" (ABI) and it is how all 32 bit Windows API code is written. If you properly observe the ABI design, you will not have problems with mysterious register overwrites, this is why the system is designed this way. If you go to the help file "ASM Intro Help" and go to the link "Register Preservation Convention" you will see how it works. It looks complicated but is really simple in operation.
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: MichaelW on March 03, 2016, 03:10:00 PM

include \masm32\include\masm32rt.inc
.data
val1 DWORD 1000h
.code
start:
    mov eax, val1
    print hex$(val1),13,10
    print hex$(eax),13,10
    inkey   
    mov eax, val1
    push  eax
    print hex$(val1),13,10
    pop   eax
    print hex$(eax),13,10
    inkey       
  exit
end start

    hex$ MACRO DDvalue
      LOCAL rvstring
      .data
        rvstring db 12 dup (0)
        align 4
      .code
      invoke dw2hex,DDvalue,ADDR rvstring
      EXITM <ADDR rvstring>
    ENDM

; ########################################################################
;
;               This original module was written by f0dder.
;
;      Part of the code has been optimised by Alexander Yackubtchik
;
; ########################################################################

    .386
    .model flat, stdcall
    option casemap :none   ; case sensitive

    .code

; ########################################################################

; THIS CODE CONTAINS 6 INSTRUCTIONS THAT MODIFY, OR POTENTIALLY MODIFY,
; EAX WITHOUT PRESERVING ITS VALUE, IN PERFECT CONFORMANCE WITH THE ABI.

dw2hex proc source:DWORD, lpBuffer:DWORD

    push esi

    mov edx, lpBuffer
    mov esi, source

    xor eax, eax
    xor ecx, ecx

    mov [edx+8], al         ; put terminator at correct length
    mov cl, 7               ; length of hexstring - 1

  @@:
    mov eax, esi            ; we're going to work on AL
    and al, 00001111b       ; mask out high nibble

    cmp al,10
    sbb al,69h
    das

    mov [edx + ecx], al     ; store the asciihex(AL) in the string
    shr esi, 4              ; next nibble
    dec ecx                 ; decrease counter (one byte less than dec cl :-)
    jns @B                  ; eat them if there's any more

    pop esi

    ret

dw2hex endp

; #########################################################################

end


00001000
00000002
Press any key to continue ...
00001000
00001000
Press any key to continue ...


Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on March 04, 2016, 06:56:20 PM
This means that if you must store values in any of the 3 mentioned registers and then call other procedures, you must preserve any of EAX ECX EDX before you call another procedure and restore them after it has returned.

So how do I get MASM to preserve the values in those three registers? Also, I'm not really sure what "restoring them" means.


The solution is to use LOCAL variables to get the procedure running reliably then selectively replace them with any registers that may not be used in the procedure. With careful register reuse you can reduce the number of LOCAL variables by using registers and produce faster code if you get it right.


I'm assuming that variables are local to the procedure that they're declared and used in. So how do you get MASM to treat variables as global? For example, are val1 and val2 considered global variables in the following code:

include \masm32\include\masm32rt.inc
.data
val1 DWORD 1000h
val2 DWORD 2000h

.code
start:

    mov eax, val1 ; eax should now have 1000h
   
    xchg eax, val2 ; eax should now have 2000h, and val2 should now be 1000h instead of 2000h
   
    mov val1, eax ; val1 should now have 2000h instead of 1000h

   
    print hex$(val1),13,10 ; result: 00002000

    ;What must I do to preserve eax, so that the result stays "00002000"?

    print hex$(eax),13,10 ; result: 00000002   
   

    inkey "We've made it through the operations without errors!"
   
  nop ; no operation left to perform

  inkey "End of program."
  exit
end start
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on March 04, 2016, 08:57:05 PM
push = preserve
pop =restore

Ensure you pop registers in REVERSE order to what you push them in.

Like this


push ebx
push esi
push edi

; run your code here

pop edi
pop esi
pop ebx
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: hutch-- on March 05, 2016, 12:21:16 AM
Red,

Here is a simple test piece that shows how to use the old instruction XCHG. You would not normally write it this way but it is done so you can understand it.


; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤
    include \masm32\include\masm32rt.inc
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *

    .code

start:
   
; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

    call main
    inkey
    exit

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

main proc

    LOCAL var1  :DWORD
    LOCAL var2  :DWORD

    push esi
    push edi

    mov var1, 12345678
    mov var2, 87654321

    print "Before XCHG",13,10
    print str$(var1)," var1",13,10
    print str$(var2)," var2",13,10,13,10

    mov esi, var1
    mov edi, var2

  ; ***************************

    xchg esi, edi       ; exchange the two registers

  ; ***************************

    mov var1, esi
    mov var2, edi

    print "After XCHG",13,10
    print str$(var1)," var1",13,10
    print str$(var2)," var2",13,10


    pop edi
    pop esi

    ret

main endp

; ¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤

end start
Title: Re: Taking care of the prerequisites to create my first program without VS
Post by: RedSkeleton007 on March 27, 2016, 12:46:32 PM
Quote from: hutch-- on March 05, 2016, 12:21:16 AM

main proc

    LOCAL var1  :DWORD
    LOCAL var2  :DWORD ;Why didn't you need to use [b]?[/b] to indicate that the variables are uninitialized?

    push esi ;Why are you pushing a register onto the stack before storing var1 or var2 in it?
    push edi

    mov var1, 12345678
    mov var2, 87654321

    print "Before XCHG",13,10
    print str$(var1)," var1",13,10
    print str$(var2)," var2",13,10,13,10

    mov esi, var1
    mov edi, var2