News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

My first assembly language program!!!

Started by srod, November 22, 2006, 09:46:19 PM

Previous topic - Next topic

srod

Yay!!!

I'm finally getting somewhere with assembly language (thanks to GoAsm!)

I'd thought I'd post my first prog as I am hell bent on becoming proficient with assembly language and I'm kind of hoping that some of you GoAsm gurus might cast a critical eye on the code and give me a few pointers/suggestions for improvements etc.

I'm sure I've produced something very inefficient here!

All it does is, when called from another object file, writes the contents of the EAX, AX and AL registers to the console. I've pinched some of the code from the GoAsm manual for the reverse storage of the individual characters etc.

;GoAsm.
;Dump EAX, AX and AL registers by Stephen Rodriguez; Nov 2006.


#include c:\GoAsm\IncludeA\Windows.inc


CONSTANT SECTION
DReg_MESSAGE dd 45
db 'EAX register dump utility - S. Rodriguez.',10,13, 10, 13   


DATA SECTION
;
DReg_TEMP dd 0
DReg_BUFFER dd 0
db 256 DUP 0
DReg_HANDLE dd 0
DReg_REGISTER dd 0
;
CODE SECTION
;
DUMPEAX:
;Push the registers we wish to use and the flags.
PUSH EAX, EBX, ECX, EDX, EDI
PUSHFD

MOV [DReg_REGISTER], EAX ;For safe keeping!

;Display initial message.
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
MOV [DReg_HANDLE], EAX ;Store for later use.
INVOKE WriteFile, eax, addr DReg_MESSAGE+4, [DReg_MESSAGE], ADDR DReg_TEMP, 0

;Display the full register.
MOV [DReg_BUFFER+4], 'EAX '
MOV D[DReg_BUFFER], 4
MOV EDI, ADDR DReg_BUFFER+8 ;Address of buffer to receive the ascii digits.
CALL DReg_EAX

;Display the AX register.
XOR EAX, EAX
MOV AX, [DReg_REGISTER]
MOV [DReg_REGISTER], EAX
MOV [DReg_BUFFER+4], '-AX '
MOV D[DReg_BUFFER], 4
MOV EDI, ADDR DReg_BUFFER+8 ;Address of buffer to receive the ascii digits.
CALL DReg_EAX

;Display the AL register.
XOR EAX, EAX
MOV AL, [DReg_REGISTER]
MOV [DReg_REGISTER], EAX
MOV [DReg_BUFFER+4], '-AL '
MOV D[DReg_BUFFER], 4
MOV EDI, ADDR DReg_BUFFER+8 ;Address of buffer to receive the ascii digits.
CALL DReg_EAX

;Wait for the user to hit the return key.
INVOKE GetStdHandle, STD_INPUT_HANDLE
INVOKE ReadConsoleA, EAX, addr DReg_BUFFER, 256, ADDR DReg_TEMP, 0

POPFD
POP EDI, EDX, ECX, EBX, EAX
RET

;The following proc displays the contents of EAX.
DReg_EAX: ;This routine is based on code taken from the GoAsm manual.
MOV EAX, [DReg_REGISTER]  ;Contains the value to output.
XOR EDX,EDX
XOR ECX,ECX
CLD ;Clear direction.
MOV EBX,10
:
DIV EBX          ;div edx:eax by 10 = quotient in eax, remainder in edx
PUSH EDX                ;keep result on the stack
INC ECX                  ;count how many are done (we'll need this in order to output the result).
XOR EDX,EDX              ;zero edx
CMP EAX,EDX             ;see if any more to do
JNZ <                 ;yes
ADD [DReg_BUFFER], ECX ;Store the number of digits.
ADD D[DReg_BUFFER], 2
:                      ;now reverse the order of the digits
POP EAX                  ;get next back from the stack
ADD AL,48                 ;convert to ascii number
STOSB                    ;write ascii number to buffer
LOOP :                  ;continue while ecx is not zero
;Add the end of line characters.
MOV b[EDI], 10
MOV b[EDI+1], 13
;Now display the number.
INVOKE WriteFile, [DReg_HANDLE], addr DReg_BUFFER+4, [DReg_BUFFER], ADDR DReg_TEMP, 0
RET


Thanks in advance.

Stephen.

donkey

Quote from: srod on November 22, 2006, 09:46:19 PM
Yay!!!

I'm finally getting somewhere with assembly language (thanks to GoAsm!)

Congrats !!!

QuoteI'm sure I've produced something very inefficient here!

I wouldn't spend too much time worrying about efficiency right now, it is more important to get results, when you become more familiar with the instruction set and architecture then you can cycle-count if you are so inclined. But in reality, processors are extremely fast and the caching algorithms very advanced so for the most part unless you are doing some serious number crunching (ie 3D animation) or huge iterations you will never notice the difference. After all, if you have a procedure that takes 1000 cycles and you shave that down to 200 you may have saved 80% but on a 1GHz system it amounts to 0.0000007 seconds, based on about 0.05 seconds being the smallest noticable time interval it would require 71,400 iterations before you would notice. Some people make too much out of optimizing and lose sight of ease of use and practicality. The other trap is executable size, though this can be important there is no need to write another 1K message box, most users have 256MB or better and many have 1GB or better, saving a few K's holds little meaning anymore.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

srod

Thanks. I agree entirely with what you said there.

btw, does anyone know of a good guide for assembly language mnemonics - I mean the 8086 instruction set rather than pre-processor statements etc? I have one, but it is as easy to read as a doctor's prescription!

Thanks.

gabor

Hello!

There is a help file in the MASM package about the basic instructiopn set. I'll better post it for ya!

btw. Good work! Keep it going!  :U

Greets, Gábor

[attachment deleted by admin]

srod

hehe, same one that I already have!!!  :bg

I'm getting used to it though and have managed to acquire a copy of Kip Irvine's book which makes for excellent reading. Between these and GoAsm's manual, I'm starting to see the light!

Thanks anyhow, much appreciated.

Another question though (if you don't mind?)

If I want to branch if the value in EAX is less than 10 (unsigned), I can't quite get my head around the order.

E.g.


CMP EAX, 10
JB mylabel


Have I got this right or do I need JA?  I'm just a little confused because I seem to have contradictory examples in front of me!

Thanks.

donkey

Hi srod,

The best reference I have found in HLP format is the x86eas.hlp file (up to MMX), I have a link to it on my website but here it is directly...

http://www.assembler.ca/files/x86eas.zip

You have the right jmp (sort of), it will branch if the value in EAX is below 10, cmp always compares the first operand to the second and set the flags accordingly, so in this case it would compare EAX to 10 and flag it as below, equal or above. BTW watch for signs when selecting conditional branches, remember that 0xFFFFFFFF (-1) is both greater than 0 and less than 0 depending on whether you are doing a signed branch or not. In the case of JB, it is an unsigned branch so -1 will be determined to be greater than 0, JL is the signed version of the branch so in it's case -1 is less than 0. In Intel semantics, Below and Above are unsigned conditional branches and Less and Greater are signed conditional branches.

Edgar
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

bushpilot

Quote from: donkey on November 25, 2006, 04:40:18 AM
In Intel semantics, Below and Above are unsigned conditional branches and Less and Greater are signed conditional branches.

I imagine a LG sign (billboard) on a road I use - that is how I remember which is signed and which is not.

Greg

srod

Excellent, thanks guys. I was actually convinvced I'd got the wrong jump!

Thanks for the link Donkey.