Falco's MSP430 (and now x86) Assembly Programs
Moderator: Coders of Rage
- Netwatcher
- Chaos Rift Junior
- Posts: 378
- Joined: Sun Jun 07, 2009 2:49 am
- Current Project: The Awesome Game (Actual title)
- Favorite Gaming Platforms: Cabbage, Ground beef
- Programming Language of Choice: C++
- Location: Rehovot, Israel
Re: Falco's MSP430 Assembly Programs
Been wanting to learn asm for some time now,today seems like a good day to start
Thanks Falco!
Thanks Falco!
"Programmers are the Gods of their tiny worlds. They create something out of nothing. In their command-line universe, they say when it’s sunny and when it rains. And the tiny universe complies."
-Derek Powazek, http://powazek.com/posts/1655
blip.fm DJ profile - http://blip.fm/Noobay
current code project http://sourceforge.net/projects/vulcanengine/
-Derek Powazek, http://powazek.com/posts/1655
blip.fm DJ profile - http://blip.fm/Noobay
current code project http://sourceforge.net/projects/vulcanengine/
- RyanPridgeon
- Chaos Rift Maniac
- Posts: 447
- Joined: Sun Sep 21, 2008 1:34 pm
- Current Project: "Triangle"
- Favorite Gaming Platforms: PC
- Programming Language of Choice: C/C++
- Location: UK
- Contact:
Re: Falco's MSP430 Assembly Programs
I was just wondering, what would you suggest is the best way to start learning assembly? I mean, any useful tools / good compilers / useful resource sites? I've always been interested but never really knew where to begin.
Re: Falco's MSP430 Assembly Programs
mmm... id say the best way is to actually learn it in school. college what ever. its a hard topic to do on your own..RyanPridgeon wrote:I was just wondering, what would you suggest is the best way to start learning assembly? I mean, any useful tools / good compilers / useful resource sites? I've always been interested but never really knew where to begin.
what you can do is to delve through college asm courses and get all the notes you can. also. get a good book, something like "assembly language for intel-based computers" but kip irvine. its probably the best book on the topic.
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Dad, "Yea well I have a fan belt in street fighting"
- short
- ES Beta Backer
- Posts: 548
- Joined: Thu Apr 30, 2009 2:22 am
- Current Project: c++, c
- Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
- Programming Language of Choice: c, c++
- Location: Oregon, US
Re: Falco's MSP430 Assembly Programs
That's the book i learned in my cs course.avansc wrote:mmm... id say the best way is to actually learn it in school. college what ever. its a hard topic to do on your own..RyanPridgeon wrote:I was just wondering, what would you suggest is the best way to start learning assembly? I mean, any useful tools / good compilers / useful resource sites? I've always been interested but never really knew where to begin.
what you can do is to delve through college asm courses and get all the notes you can. also. get a good book, something like "assembly language for intel-based computers" but kip irvine. its probably the best book on the topic.
In the class I learned in, we used gnu compiler with cygwin if you used windows. Also OllyDbg was what they suggested you used as a debugger.
Personally, I preferred visual studio 2008 c++ for my compiling. I especially liked it when we did inline assembly. It took a lot of configuring, but that can all be found online. Honestly though, OllyDbg is really powerful, and I wish I had taken the time to learn it better. I know there is a lot of uses for reverse engineering I've read, if that's your kind of thing. Eventually I plan to head that way, it is extremely fascinating to me.
/back on topic.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
link: https://github.com/bjadamson
Re: Falco's MSP430 Assembly Programs
i assume it was a course on asm?
but yeah. odbg is great. if there is any goal a asm course should have is to teach you
how to use a debugger.
i prefer the borland assmebler.
tasm. with its respective debugger.
but yeah. odbg is great. if there is any goal a asm course should have is to teach you
how to use a debugger.
i prefer the borland assmebler.
tasm. with its respective debugger.
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Dad, "Yea well I have a fan belt in street fighting"
- short
- ES Beta Backer
- Posts: 548
- Joined: Thu Apr 30, 2009 2:22 am
- Current Project: c++, c
- Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
- Programming Language of Choice: c, c++
- Location: Oregon, US
Re: Falco's MSP430 Assembly Programs
It was half the course's objective. In my opinion I believe the instructor did a poor job showing us how to use the debugger.avansc wrote:i assume it was a course on asm?
but yeah. odbg is great. if there is any goal a asm course should have is to teach you
how to use a debugger.
i prefer the borland assmebler.
tasm. with its respective debugger.
Would you say a debugger such as ollydbg is different then a normal compiler?
It seems like OllyDBG was a lot more low level then my C debugger.
If I remember correctly, you could feed it an executable and debug the actual debugger. Much different then say mvsc++ debugger.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
link: https://github.com/bjadamson
- captjack
- Chaos Rift Cool Newbie
- Posts: 50
- Joined: Fri Sep 18, 2009 4:23 pm
- Current Project: engine framework
- Favorite Gaming Platforms: PC, XBox 360, PS3
- Programming Language of Choice: C, C++
- Location: Northern Virginia
Re: Falco's MSP430 Assembly Programs
Ah, assembly!
I have memories of my kernel days. Nothing like writing code for a computer and not having the benefit of a standard library. The power of rolling one's own printf, farting around with scan codes for the keyboard driver, getting the global descriptor table set up correctly and unwinding all the triple faults!
I said, "fuck it" and went to game programming instead.
-capt jack
I have memories of my kernel days. Nothing like writing code for a computer and not having the benefit of a standard library. The power of rolling one's own printf, farting around with scan codes for the keyboard driver, getting the global descriptor table set up correctly and unwinding all the triple faults!
I said, "fuck it" and went to game programming instead.
-capt jack
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: Falco's MSP430 (and now x86) Assembly Programs
So Kendall's homework assignment was to create a simple number guessing game in x86 assembly. It requires a random number between 1 and 100 to be generated, and must tell the user whether his guess is too high or too low. It also must keep track of and print the number of guesses.
Not only that, but it had to check whether the damn things were valid input or not.
I just got done helping with it (she got it started), and here's the source:
(She does the algorithms homework, I do the assembly. )I find x86 quite a bit easier than MSP430. There's addressing modes for everything. I don't even have to worry about moving things from RAM into registers if I don't have to. There's also opcodes to handle all sorts of things (that MSP430 makes you do manually).
Not only that, but it had to check whether the damn things were valid input or not.
I just got done helping with it (she got it started), and here's the source:
(She does the algorithms homework, I do the assembly. )
Code: Select all
;----------------------------------------------------;
; Student -- Kendall Hyatt ;
; ID Number -- A25009697 ;
; Email -- Kendall.S.Hyatt@gmail.com ;
; Course -- CS 308 (Assembly Language) ;
; Instructor -- Joe Toone ;
; Assignment -- Program 1 ;
; Problem -- Random Number Game ;
; Due Date -- 09/30/2009 ;
;----------------------------------------------------;
TITLE PROG1.ASM ;DOS file name of program
LF equ 0ah ;ASCII 10d - newline character
CR equ 0dh ;ASCII 13d - carriage return character
DOUBLESPC equ CR,LF,LF ;ASCII 13,10,10 - for double space line
.MODEL SMALL ;Memory model is Small
.286 ;Allow for pusha and popa instrucitons
.STACK 100h ;100 hex bytes for stack
.DATA ;Data segment begins here
RandNum DB DOUBLESPC,'Your random number is: $'
Gener DB DOUBLESPC, 'Your number has been generated. $'
Prompt DB DOUBLESPC, 'Enter a guess (1-100): $'
InvalidStr DB DOUBLESPC,'Invalid input, try again! $'
Hundredth DB ?
CheckAgain DB DOUBLESPC,'Would you like to play (Y/N)?$'
CharTyped DB ?
Guess DW 0h ; Allocates a place in memory for our current guess
TotalGuess DB 0h ; Contains total number of guesses
TooHigh DB DOUBLESPC,'Your guess was TOO HIGH! Try again: $'
TooLow DB DOUBLESPC,'Your guess was TOO LOW! Try again: $'
Winner DB DOUBLESPC,'YEAH! That is it! It only took you $'
Tries DB ' tries. $'
Error DB DOUBLESPC,'You must enter an integer between 1 and 100. Try again: $'
Spaces DB DOUBLESPC,'$'
;***************************************************************************
;************************* Main Body of Program ****************************
;***************************************************************************
;********************************** MAIN ***********************************
; Requires -- Nothing
; Process -- Main Body - calls procedures to do the processing
; Returns -- Nothing
;***************************************************************************
.CODE ;executable section begins here
_main: mov ax,@data ;starting address of data segment
mov ds, ax ;set DS to point to the data segment
DoOver: mov TotalGuess, 0h
lea dx,CheckAgain ;Point to the question prompt
call PrintString ;go print the string
call GetChar ;Get a character from the keyboard
mov CharTyped,al ;save the character that was typed
cmp CharTyped,'y' ;Was lowercase y for get time?
je CTime ;yes, jump to get time
cmp CharTyped,'Y' ;Was uppercase Y for get time?
je CTime ;yes, jump to get time
cmp CharTyped, 'n' ;was lowercase y for get time?
je AllDone ;nope, end program
cmp CharTyped, 'N' ;was uppercase Y for get time?
je AllDone ;yep, end program
jmp TryAgain ;Not an option? Invalid input
CTime: call clock ;Go check the system clock
mov Hundredth,dl ;and save hundredths
; lea dx,RandNum
; call PrintString
; mov al,Hundredth UNCOMMENT ME TO CHEAT!!!!
; mov ah,0h
; call ShowNum
; jmp DoOver
lea dx, Gener ;Copy location of "number generated" string
call PrintString ;Display string
GameSet:lea dx,Prompt ;point to game prompt string
call PrintString ;go print the string
call Ascii2Int ;get guess from user
cmp ax, 0d ;Check if the guess is 0
je Invalid ;It is, invalid input
mov Guess,ax ;Copy the location of the guess to ax
lea dx,Spaces ;Copy the location of Spaces to dx
call PrintString ;Print spaces
call Int2Ascii ;Convert our integer guess to ascii and print
call JdgGuess ;Judge our guess
; Check status of guess
cmp dx, 1 ;If the flag is true, we got it right
je DoOver ;Start the game over
jmp GameSet ;Otherwise it was wrong, start another guess
AllDone:mov ax,4c00h ;DOS terminate program function #
int 21h ;terminate the program
Invalid:lea dx, InvalidStr ;Copies invalid string address to dx
call PrintString ;Prints error
jmp GameSet ;Jumps back to guessing
TryAgain: lea dx, InvalidStr ;Copies invalid string address to dx
call PrintString ;Prints error
jmp DoOver ;Jumps back to "Play again?"
;***************************************************************************
;************************ SubRoutines/Procedures ***************************
;***************************************************************************
;******************************* JdgGuess ***********************************
; Requires -- User guess in register AX
; Process -- Judges whether the guess was too high, too low, correct, and sets flags
; Returns -- Status flag in DX (1 is correct, 0 is wrong)
;***************************************************************************
JdgGuess PROC
inc TotalGuess
mov bl, Hundredth
mov bh, 0h
cmp ax, bx
jg Greater
jl Less
je Equal
Equal: lea dx, Winner
call PrintString
mov al, TotalGuess
mov ah, 0h
call Int2Ascii
lea dx, Tries
call PrintString
mov dx, 1
ret
Greater:lea dx, TooHigh
call PrintString
mov dx, 0
ret
Less: lea dx, TooLow
call PrintString
mov dx, 0
ret
JdgGuess ENDP
;******************************* GetChar ***********************************
; Requires -- Nothing
; Process -- Input a character using DOS function #1 and interrupt 21h
; Returns -- The input character in AL register
;***************************************************************************
GetChar PROC ;Define procedure
push bx ;Protect some registers
push cx ;
push dx ;
mov ah,01h ;DOS get character function #1
int 21h ;Get the character
pop dx ;Restore some resgisters
pop cx ;
pop bx ;
ret ;Return to calling procedure
GetChar ENDP ;End of procedure
;******************************* PutChar ***********************************
; Requires -- The character to be printed must be in the DL register
; Process -- Print a character by using DOS function #2 and interrupt 21h
; Returns -- Nothing
;***************************************************************************
PutChar PROC ;Define procedure
pusha ;Protect all registers
mov ah,02h ;DOS print character function #2
int 21h ;Get the character
popa ;Restore all registers
ret ;Return to calling procedure
PutChar ENDP ;End of procedure
;***************************** PrintString *********************************
; Requires -- The address of $-terminated string to print in the DX register
; Process -- Print the string using DOS function #9 and interrupt 21h
; Returns -- Nothing
;***************************************************************************
PrintString PROC ;Define procedure
pusha ;Protect all registers
mov ah,9h ;DOS print string function #9
int 21h ;display the string
popa ;Restore all registers
ret ;Return to calling procedure
PrintString ENDP ;End of procedure
;***************************** PrintString *********************************
; Requires -- The address of $-terminated string to print in the DX register
; Process -- Print the string using DOS function #9 and interrupt 21h
; Returns -- Nothing
;***************************************************************************
Random PROC ;define procedure
mov bx,251d ;just goof up the number
mul bx
add ax,138d ;add stuff to it
mov ah,0d ;zero the high byte
and al,0fh ;mask the low nibble
ret ;return to caller
Random ENDP ;end of procedure
;********************* Procedure to Read System Clock *************************
; Given : Nothing
; Process : Read the system time of day clock for hour, minute, second, and
; : 1/100 of a second
; Notes : Using this procedure (as written) will destroy the contents of
; : AH, CX, and DX registers
; Return : Return CH=hour CL=minute DH=second DL=100th of a second
; Author : Joe Toone
;******************************************************************************
Clock PROC
mov ah,2ch ;DOS function #2C reads time of day
int 21h ;CH=hour CL=minute DH=second DL=100th sec
ret ;Return to calling procedure
Clock ENDP
;********************** Procedure to Print the Number *************************
; Given : The integer to be printed in the AX register
; Process : Convert the integer to a string of ASCII digits and print them
; one at the time, until all are printed
; Return : Nothing
;******************************************************************************
ShowNum PROC
pusha ;Save the contents of all registers
mov cx,0h ;Zero the CX register for digit counter
mov bx,10d ;Set up divisor of 10 decimal
NextOut:mov dx,0h ;Zero DX reg for high order word of div
div bx ;Divide number in AX by 10
push dx ;Save remainder on the stack
inc cx ;Count the digit
cmp ax,0h ;Is number in AX greater than 0
jg NextOut ;Yes, get next digit
CharOut:pop ax ;Get number from the stack
add ax,30h ;Convert number to ASCII character
mov dl,al ;Move to character print register
call PutChar ;Print the character
dec cx ;Reduce characters to print by one
jnz CharOut ;If CX > 0 loop to print next digit
popa ;Restore the registers
ret ;Return to Calling procedure
ShowNum ENDP ;end of procedure
;********************** Procedure to Input the Number *************************
; Requires : Nothing
; Process : Accept a string of ASCII digits and convert them to an integer
; Returns : Return the integer in AX register
;******************************************************************************
Ascii2Int PROC
push bx ;Save the contents of all registers
push cx ; except for AX, which will contain the
push dx ; number which was read
mov bx,0h ;Zero the BX register
NextDigit: mov ah,1h ;DOS input character function #1 hex
int 21h ;Get a character
cmp al,'0' ;If the character is less than 0, then
jl Done ; we have all the number and are Done
cmp al,'9' ;If the character is more than 9, then
jg Done ; we have all the number and are Done
sub al,30h ;Convert ASCII to integer value
xor ah,ah ;Zero the high byte of AX
push ax ;Save the digit on the stack
mov ax,10d ;Place 10 decimal in AX to multiply by
mul bx ;Multiply the number by 10
mov bx,ax ;Get number from AX and put in BX
pop ax ;Get the digit back from the stack
add bx,ax ;Add the digit to the number
jmp NextDigit ;Get the next digit
Done: mov ax,bx ;Return the NUMBER in AX register
pop dx ;Restore the registers in reverse order
pop cx ;
pop bx ;
ret ;Return to Calling procedure
Ascii2Int ENDP
;********************** Procedure to Print the Number *************************
; Requires : The integer to be printed in the AX register
; Process : Convert the integer to a string of ASCII digits and print them
; one at the time, until all are printed
; Returns : Nothing
;******************************************************************************
Int2Ascii PROC
pusha ;Save the contents of all registers
mov cx,0h ;Zero the CX register for digit counter
mov bx,10d ;Set up divisor of 10 decimal
NextOut2:mov dx,0h ;Zero DX reg for high order word of div
div bx ;Divide number in AX by 10
push dx ;Save remainder on the stack
inc cx ;Count the digit
cmp ax,0h ;Is number in AX greater than 0
jg NextOut2 ;Yes, get next digit
CharOut2:pop ax ;Get number from the stack
add ax,30h ;Convert number to ASCII character
mov dl,al ;Move to character print register
call PutChar ;Print the character
dec cx ;Reduce characters to print by one
jnz CharOut2 ;If CX > 0 loop to print next digit
popa ;Restore the registers
ret ;Return to Calling procedure
Int2Ascii ENDP
END _main ;code segment ends here
Re: Falco's MSP430 (and now x86) Assembly Programs
JdgGuess PROC
inc TotalGuess
mov bl, Hundredth
mov bh, 0h
cmp ax, bx
jg Greater
jl Less
je Equal -- this is redundant
Equal: lea dx, Winner
also, look at xlat. it translates chars depending on how you want. that way you dont have to check 4 times fir yYnN but just twice, which will resuly in only one jump and not 4.
you could also make a casetable
something like
(from my old notes, and probably from my asm book)
NE = 4
CaseTable db 'y' ; lookup
dw proc1 ; address of proc
db 'Y' ; lookup
dw proc1 ; address of proc
db 'n' ; lookup
dw proc2 ; address of proc
db 'N' ; lookup
dw proc2 ; address of proc
.code
mov al,input
mov bx, offset CaseTable
moc cx, NE
L1: cmp al, [bx]
jne L2
call word ptr [bx+1]
jmp L3
L2: add bx,3
loop L1
L3:
inc TotalGuess
mov bl, Hundredth
mov bh, 0h
cmp ax, bx
jg Greater
jl Less
je Equal -- this is redundant
Equal: lea dx, Winner
also, look at xlat. it translates chars depending on how you want. that way you dont have to check 4 times fir yYnN but just twice, which will resuly in only one jump and not 4.
you could also make a casetable
something like
(from my old notes, and probably from my asm book)
NE = 4
CaseTable db 'y' ; lookup
dw proc1 ; address of proc
db 'Y' ; lookup
dw proc1 ; address of proc
db 'n' ; lookup
dw proc2 ; address of proc
db 'N' ; lookup
dw proc2 ; address of proc
.code
mov al,input
mov bx, offset CaseTable
moc cx, NE
L1: cmp al, [bx]
jne L2
call word ptr [bx+1]
jmp L3
L2: add bx,3
loop L1
L3:
Some person, "I have a black belt in karate"
Dad, "Yea well I have a fan belt in street fighting"
Dad, "Yea well I have a fan belt in street fighting"
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: Falco's MSP430 (and now x86) Assembly Programs
Alrighty, I'm back to the MSP430 processor. The processor was built without CPU multiplication to keep down costs and keep up clock frequency. Instead, many MSP430 models come with additional multiplication units that receive multiplicands and multipliers in special registers, and perform the computation (independent of the CPU).
Our instructor wanted us to implement software multiplication of two signed 8-bit numbers (shift and add), he also wanted us to do it with the hardware multiplier. Then the final assignment was to use the hardware multiplier's "multiply and accumulate" to take the dot product of vectors. It was a two week assignment, and I just got off my lazy ass and did it this morning (due in less than an hour).
Here we have software multiplication:
Here we have hardware multiplication:
And we have the dot product (using the hardware multiplier):
...and for the lulz here's my sloppy ass main that I threw together to drive these examples:
Our instructor wanted us to implement software multiplication of two signed 8-bit numbers (shift and add), he also wanted us to do it with the hardware multiplier. Then the final assignment was to use the hardware multiplier's "multiply and accumulate" to take the dot product of vectors. It was a two week assignment, and I just got off my lazy ass and did it this morning (due in less than an hour).
Here we have software multiplication:
Code: Select all
/* Falco Girgis
* CPE323 Lab Section 2
* Lab Assignment #3
*
* Software Multiplication Routine
* R13 - 8-bit Signed Multiplicand
* R14 - 8-bit Signed Multiplier
* R15 - 16-bit Signed Result
*
* R10 - Used as a flag for negative result
* R11 - Used as a counter (both are restored)
*/
#include "msp430.h"
PUBLIC soft_mult ; Routine available from elsewhere
RSEG CODE
soft_mult: PUSH R10 ; Preserve these registers
PUSH R11
CLR R10 ; Clear registers for use
CLR R11
CLR R15
mplcndChk: BIT.B #10000000b, R13 ; Check to see if multiplicand is negative
JNC mplierChk ; If not, jump to check multiplier
INV.B R13
INC.B R13 ; Take twos compliment
INC R10 ; Update negative answer flag
mplierChk: BIT.B #10000000b, R14 ; Check if multiplier is negative
JNC mult ; If not, proceed with unsigned multiplication
INV.B R14
INC.B R14 ; Take twos compliment
INC R10 ; Update negative answer flag
mult: BIT.B #00000001b, R14 ; Check first digit of multiplier
JC copy ; Copy multiplicand to result if so
JMP rotate ; Jump to rotate loop if not
copy: MOV R13, R15
rotate: INC R11 ; Increment counter
CMP #5, R11 ; Check if we're done looping to last bit
JEQ signChk ; If we are, jump to check if result is signed
RLA R13 ; Rotate multiplicand left
RRA R14 ; Rotate multiplier right
BIT.B #00000001b, R14 ; Check if first bit of multiplier is 1
JNC rotate ; If not, proceed with next iteration
ADD R13, R15 ; If so, add current multiplicand to running total
signChk: CMP #1d, R10 ; If our flag is 1, the result should be signed
JEQ signAns
JMP endMult
signAns: INV R15 ; Twos compliments result
INC R15
endMult: POP R11
POP R10
RET
END
Code: Select all
/* Falco Girgis
* CPE323 Lab Section 2
* Lab Assignment #3
*
* Hardware Multiplication Routine
* R13 - 8-bit Signed Multiplicand
* R14 - 8-bit Signed Multiplier
* R15 - 16-bit Signed Result
*/
#include "msp430.h"
PUBLIC hard_mult ; Routine available from elsewhere
RSEG CODE
hard_mult: MOV R13, &MPYS ; Move first operand to signed mult register
SXT &MPYS ; Sign extend
MOV R14, &OP2 ; Moves second operand to OP2 register
SXT &OP2 ; Sign extend
MOV RESLO, R15 ; Return result through register R15
RET
END
Code: Select all
/* Falco Girgis
* CPE323 Lab Section 2
* Lab Assignment #3
*
* Dot Product with Hardware Multiplier (and Accumulate)
* R12 - Address of 8-bit signed integer array
* R13 - Address of 8-bit signed integer array
* R14 - Length of the two arrays
* R15 - Return product
*/
#include "msp430.h"
PUBLIC hard_dot ; Routine available from elsewhere
RSEG CODE
hard_dot:
PUSH R10 ; Preserve contents of R10
CLR R10 ; Clear counter
INC R14 ; We're looping to length+1, increment length
dot_loop: INC R10 ; Increment counter
CMP R10, R14 ; Check if we have looped to > length
JEQ end_dot ; If so, end
MOV @R12+, &MACS ; Copy first entry of array to multiplier and increase address
MOV @R13+, &OP2 ; Copy second entry of array to multiplier and increase address
JMP dot_loop ; Repeat loop
end_dot: MOV RESLO, R15 ; Move result to return register
POP R10 ; Restore register R10
RET
END
Code: Select all
#include "msp430.h"
NAME main ; module name
PUBLIC main ; make main accessible from outside module
EXTERN soft_mult
EXTERN hard_mult
EXTERN hard_dot
ORG 0FFFEh
DC16 init ; set reset vector to 'init' label
RSEG CSTACK ; pre-declaration of segment CSTACK
RSEG CODE ; place program in 'CODE' segment
init: MOV #SFE(CSTACK), SP ; initialize stack
/*
//Software multiplication main
main: NOP ; main entry point
MOV.W #WDTPW+WDTHOLD,&WDTCTL ; stop watchdog timer
MOV.B arr1, R13 ; Moves arguments into parameter registers
MOV.B arr2, R14
CALL #soft_mult ; Calls soft multiplication routine
JMP $
arr1 DB -3d
arr2 DB -5d
*/
/*
// HARDWARE MULTIPLICATION MAIN
main: NOP ; main entry point
MOV.W #WDTPW+WDTHOLD,&WDTCTL ; stop watchdog timer
MOV.B arr1, R13 ;Moves argument #1 into R13
MOV.B arr2, R14 ;Moves argument #2 into R14
CALL #hard_mult ;Calls hardware multiplication routine
JMP $
arr1 DB 3d
arr2 DB -18d
*/
// DOT PRODUCT MAIN
/*
main: NOP ; main entry point
MOV.W #WDTPW+WDTHOLD,&WDTCTL ; stop watchdog timer
MOV #arr1, R12 ;Move argument #1's memory address into R12
MOV #arr2, R13 ;Move argument #2's memory adress into R13
MOV #5, R14 ;Copy array/vector length into register R14
CALL #hard_dot ;Call hardware dot product routine
JMP $
arr1 DW -4,-2,3,4,-5
arr2 DW 2,3,4,-5,6
END
*/
Re: Falco's MSP430 (and now x86) Assembly Programs
Are you going to work with peripherals?
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: Falco's MSP430 (and now x86) Assembly Programs
Yeah, only the first third to half of the class is learning the general microprocessor. Now we're going to be doing all sorts of I/O, sampling, and embedded system designing (I know we're doing something with ethernet also).K-Bal wrote:Are you going to work with peripherals?
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: Falco's MSP430 (and now x86) Assembly Programs
Last night I completed the biggest, bitchiest, most trivial, yet pain-in-my-ass assembly project that I have ever worked on. Kendall was assigned to write a number converter in 32-bit x86 assembly. Not only that, but it has to check for any invalid input, uppercase lowercase letters in hex input, and do a bunch of annoying as hell overflow checks.
It was a two week project that took a day. I hope Kendall's teacher dies:
And a sample run:
It was a two week project that took a day. I hope Kendall's teacher dies:
Code: Select all
;*****************************************************************************
; Student -- Kendall Hyatt
; ID Number -- A25009697
; Email -- Kendall.S.Hyatt@gmail.com
; Course -- CS 308 (Assembly Language)
; Instructor -- Joe Toone
; Assignment -- Program 2
; Problem -- Binary-Decimal-Hex Converter
; Due Date -- 10/19/2009
;*****************************************************************************
TITLE PROG2.asm ;DOS file name of program
LF equ 0ah ;ASCII 10 - newline character
CR equ 0dh ;ASCII 13 - carriage return character
MAXSTR equ 256d
MAXARRAY equ 70d
MAXBINARY equ 32d ;Accept up to 32 characters for binary
MAXHEX equ 8d ;Accept up to 8 characters for hex
MAXDECIMAL equ 10d ;Accept up to 10 characters for decimal
ENABLE_PROCESSED_INPUT equ 1 ;Flag to turn off line buffering
ENABLE_PROCESSED_OUTPUT equ 1 ;Flag to turn off line buffering
ENABLE_LINE_WRAP equ 3 ;Flag to turn line wrap on
DISABLE_PROCESSED_INPUT equ 7 ;Flag to turn on line buffering
STD_INPUT equ -10d ;Function number for keyboard input
STD_OUTPUT equ -11d ;Function number for monitor output
.586 ;Allow for Pentium instrucitons
.MODEL FLAT ;Memory model is FLAT (4GB)
INCLUDELIB kernel32.lib ;Include the kernel 32 library
SetConsoleMode PROTO NEAR32 stdcall, ;Prototype for attaching to console
hConsoleHandle:DWORD, dwMode:DWORD
GetStdHandle PROTO NEAR32 stdcall, ;Prototype for obtaining a file handle
nStdHandle:DWORD
ReadFile PROTO NEAR32 stdcall, ;Prototype for reading a file
hFile:DWORD, lpBuffer:NEAR32,
nNumberOfCharsToRead:DWORD,
lpNumberOfBytesRead:NEAR32,
lpOverlapped:NEAR32
WriteFile PROTO NEAR32 stdcall, ;Prototype for writing a file
hFile:DWORD, lpBuffer:NEAR32,
nNumberOfCharsToWrite:DWORD,
lpNumberOfBytesWritten:NEAR32,
lpOverlapped:NEAR32
ExitProcess PROTO NEAR32 stdcall, ;Prototype for Exit of OS
dwExitCode:DWORD
.STACK 4096h ;4k hex bytes for stack
.DATA ;Data segment begins here
Welcome BYTE 'Welcome to the binary-decimal-hex converter ',LF,CR,
'program. You will enter a number that is either ',LF,CR,
'in binary, hexadecimal, or decimal form, and I ',LF,CR,
'will convert your number into the each of the ',LF,CR,
'other two forms and then print out all three.',LF,CR,0
Hints BYTE 'In order for me to perform, you must adhere to ',LF,CR,
'the following restrictions:',LF,CR,LF,CR,
'Binary numbers up to 32 bits',LF,CR,
'Decimal numbers no greater than 4,294,967,295',LF,CR,
'Hexadecimal values up to FFFFFFFF',LF,CR,LF,CR,
'Enjoy.',LF,CR,LF,CR,0
Prompt BYTE LF,CR,'Play now (y/n)?',LF,CR,
'(X to quit)',LF,CR,
'>>> ',0
NumSel BYTE LF,CR,'Enter the number corresponding to the base of your',
' number to be converted.',
LF,CR, '1) Base 10', LF, CR, '2) Base 16', LF, CR,
'3) Base 2', LF, CR, '4) Quit', LF, CR, LF, CR, 0
EnterDecNum BYTE LF, CR, LF, CR,
'Enter a decimal number. (less than 4294967295d)',
LF, CR, 0
EnterHexNum BYTE LF, CR, LF, CR,
'Enter a hexadecimal number. (less than 0FFFFFFFFh)',
LF, CR, 0
EnterBinNum BYTE LF, CR, LF, CR,
'Enter a binary number. (less than 33 digits)',
LF, CR, 0
Invalid BYTE LF,CR,"Invalid input. Try again.",LF,CR,0
Binary BYTE LF,CR,'Your number in binary is: ',0
Decimal BYTE LF,CR,'Your number in decimal is: ',0
Hex BYTE LF,CR,'Your number in hexadecimal is: ',0
CharTyped BYTE ?
OutArray BYTE MAXARRAY dup(?)
BlankLine BYTE LF,CR,0
String DWORD MAXARRAY dup(?)
String2 DWORD MAXARRAY dup(?)
ArrayLen DWORD ?
DigitCount DWORD ?
DecNum DWORD ?
BinNum DWORD ?
HexNum DWORD ?
Zero BYTE '0'
DoubleQuote BYTE 22h ;ASCII 34 - " character
strAddr DWORD ? ;The rest of these are used when
strLength DWORD ? ;accessing the kernel32 function
hStdOut DWORD ? ;calls.
hStdIn DWORD ?
read DWORD ?
written DWORD ?
;************************** Main Body of Program *****************************
; Given : Nothing
; Process: Main Body - calls procedures to do the processing
; Return : Nothing
;*****************************************************************************
.CODE ;executable section begins here
_main:
lea esi,Welcome ;load addr of Welcome string
call PrintString ;display welcome string
lea esi,Hints ;load addr of hints
call PrintString ;display hints
EnterChoice:
lea esi, NumSel ;load addr of number select prompt
call PrintString ;display prompt
lea esi, CharTyped ;load addr of input char
call GetChar ;get character
cmp CharTyped, '1' ;check if entering decimal
jz DecInput
cmp CharTyped, '2' ;check if entering hex
jz HexInput
cmp CharTyped, '3' ;check if entering binary
jz BinInput
cmp CharTyped, '4' ;check if quiting program
jz EndProgram
lea esi, Invalid ;anything else is invalid
call PrintString
jmp EnterChoice ;reprompt user
;****************Near procedure for Decimal Numbers**************************
; Given : Nothing
; Process : Retrieves Decimal number and converts to hex and binary
; Return : Nothing
;******************************************************************************
DecInput: ;handles decimal number input
lea esi,EnterDecNum ;load addr of prompt
call PrintString ;display prompt
lea esi,String ;load addr of input string
call GetString ;get string
call ValidateDec ;check if string is a valid decimal number
lea esi, Decimal ;load addr of prompt
call PrintString ;display prompt
lea esi, String ;load addr of decimal string
call PrintString ;display decimal string
lea esi, Hex ;load addr of prompt
call PrintString ;display prompt
lea esi, String ;load addr of decimal string input
lea edi, DecNum ;load addr for decimal integer output
call Ascii2Int ;convert from ascii to int
call DecToHex ;convert from base 10 to 16 and print
lea esi, Binary ;load addr of prompt
call PrintString ;display prompt
call DecToBin ;convert from base 10 to 2 and print
lea esi, BlankLine ;load addr of newline string
call PrintString ;display newline
jmp EnterChoice ;jump back to main menu
;****************Near procedure for Hexadecimal Numbers**************************
; Given : Nothing
; Process : Retrieves hex number and converts to binary and decimal
; Return : Nothing
;******************************************************************************
HexInput: ;handles hexadecimal number input
lea esi,EnterHexNum ;load addr of prompt
call PrintString ;display prompt
lea esi,String ;get addr of input string
call GetString ;get input string
call ValidateHex ;check to see if input is valid hex number
lea ebx, String ;load address of input
call AsciiStrToIntArray ;convert input from an ascii string to int array
call HexToDec ;convert from hex to decimal
lea esi, Decimal ;load addr of prompt
call PrintString ;display prompt
lea esi, DecNum ;load addr of decimal number
lea edi, String2 ;load addr of output string
call Int2Ascii ;convert number to ascii
lea esi, String2 ;load addr of output string
call PrintString ;print decimal string
lea esi, Hex ;load addr of hex char array
call PrintString ;display array
xor eax, eax ;clear eax
lea ebx, String ;load addr of input
mov al, BYTE PTR [ebx] ;grab the highest digit
cmp eax, 65d ;check if it's a letter
jb printh ;if not, don't bother
lea esi, Zero ;if so, print a 0 first
call PutChar
printh: lea esi, String
call PrintString ;print hexadecimal number
lea esi, Binary
call PrintString ;print prompt
call DecToBin ;print binary number
lea esi, BlankLine ;print newline
call PrintString
jmp EnterChoice ;jump back to main menu
;****************Near procedure for Binary Numbers**************************
; Given : Nothing
; Process : Retrieves Binary number and converts to hex and decimal
; Return : Nothing
;******************************************************************************
BinInput:
lea esi,EnterBinNum
call PrintString ;display prompt
lea esi,String
call GetString ;get input
call ValidateBinary ;check if it's a valid binary number
lea ebx, String
call AsciiStrToIntArray ;convert input string to array of integers
call BinToDec ;convert array to decimal number
lea esi, Decimal
call PrintString ;display prompt
lea esi, DecNum
lea edi, String2
call Int2Ascii ;convert decimal number to ascii
lea esi, String2 ;print decimal number
call PrintString
lea esi, Hex
call PrintString ;display prompt
call DecToHex ;print hexadecimal number
lea esi, Binary
call PrintString ;display prompt
lea esi, String
call PrintString ;print binary number
lea esi, BlankLine
call PrintString ;print newline
jmp EnterChoice ;back to main menu
EndProgram:
INVOKE ExitProcess, 0 ;quit program
;****************Near procedure for Binary Validation**************************
; Given : Input String in data segment
; Process : Checks to see if only valid characters were inputed and
; to make sure number is in the correct range
; Return : Nothing
;******************************************************************************
ValidateBinary PROC NEAR32
pushad ;save all registers
pushfd ;save flags
lea eax, String ;load input
xor ecx, ecx
xor ebx, ebx ;clear registers
loopbval: mov bl, BYTE PTR[eax] ;load digit
inc eax ;increment pointer
cmp bl, 0d ;check if NULL
je Quitbv
inc ecx ;increment digit counter
cmp ebx, 48d ;check if '1'
je loopbval
cmp ebx, 49d ;check if '0'
je loopbval
invb: lea esi, Invalid ;invalid input
call PrintString
call BinInput ;reprompt
Quitbv: cmp ecx, 0d
je invb
cmp ecx, 32d ;check if there's too many digits
ja invb
popfd ;restore flags
popad ;restore registers
ret
ValidateBinary ENDP
;****************Near procedure for Hexadecimal Validation**************************
; Given : Input String in data segment
; Process : Checks to see if only valid characters were inputed and
; to make sure number is in the correct range
; Return : Nothing
;******************************************************************************
ValidateHex PROC NEAR32
pushad ;save all registers
pushfd ;save flags
lea eax, String ;load input string
xor ecx, ecx
xor ebx, ebx ;clear registers
loophval: mov bl, BYTE PTR[eax] ;load digit
inc eax ;increment pointer
cmp bl, 0d ;check if NULL
je Quithv
inc ecx ;increment digit counter
cmp ebx, 48d
jb invh
cmp ebx, 58d
jb loophval
cmp ebx, 65d
jb invh ;check if it's in the correct range
cmp ebx, 71d
jb loophval
cmp ebx, 97d
jb invh
cmp ebx, 103
jb toUpper
jae invh
toUpper: sub ebx, 32
dec eax
mov BYTE PTR[eax], bl ;change from lowercase to uppercase
inc eax
jmp loophval
invh: lea esi, Invalid
call PrintString ;invalid hex number, reprompt
call HexInput
Quithv: cmp ecx, 0d
je invh
cmp ecx, 8d
ja invh ;check number of digits
popfd ;restore flags
popad ;restore registers
ret
ValidateHex ENDP
;****************Near procedure for Decimal Validation**************************
; Given : Input String in data segment
; Process : Checks to see if only valid characters were inputed and
; to make sure number is in the correct range
; Return : Nothing
;******************************************************************************
ValidateDec PROC NEAR32
pushad ;save all registers
pushfd ;save flags
lea eax, String
xor ecx, ecx
xor ebx, ebx ;clear registers
loopdval: mov bl, BYTE PTR[eax] ;load character
inc eax ;increment pointer
cmp bl, 0d
je Quitdv
inc ecx
cmp ebx, 48d ;check for correct range
jb invld
cmp ebx, 58d
jb loopdval
invld: lea esi, Invalid ;invalid input, reprompt
call PrintString
popfd
popad
call DecInput
Quitdv: cmp ecx, 0d
je invld
cmp ecx, 10d ;check number of digits
ja invld
lea esi, String
lea edi, DecNum
call Ascii2Int ;convert from string to integer
mov edi, [edi] ;to check if too large
cmp edi, 4294967295d
ja invld
popfd ;restore flags
popad ;restore registers
ret
ValidateDec ENDP
;******** Near procedure to turn an ASCII string into an Integer array ********
; Given : The address of the string in the bx register
; Process : Converts a string of ASCII characters into an array of integers (as digits)
; Return : Outputs the array and array length in the data segment
;******************************************************************************
AsciiStrToIntArray PROC NEAR32
pushad ;save all registers
pushfd ;save flags
mov [ArrayLen], -1d ;set length of array to -1
xor eax, eax
Check: mov al, BYTE PTR[ebx] ;load first char
cmp eax,0d ;check if NULL
je Quit ;quit if NULL
add ebx, 1d ;point to next character
add [ArrayLen], 1d ;increment array length
cmp eax,57d ;check alpha/num
jbe Digit ;handle number
ja Alpha ;handle letter
Digit: sub eax,48d ;sub offset
lea esi, OutArray ;load address of outArray
add esi, ArrayLen ;move to current position in outArray
mov [esi], eax ;output digit
jmp Check ;repeat loop
Alpha: sub eax,55d ;sub offset
lea esi, OutArray ;load addr of outArray
add esi, ArrayLen ;move to current position
mov [esi], eax ;output digit
jmp Check ;repeat loop
Quit: popfd ;restore flags
popad ;restore registers
ret
AsciiStrToIntArray ENDP
;****************Near procedure for Hex to Decim**************************
; Given : The address of the integer digit array in the data segment
; Process : Multiply each digit times 16 to the power of the digit number
; and add to the running total
; Return : DecNum--containing decimal number in data segment
;******************************************************************************
HexToDec PROC NEAR32
pushad ;save all registers
pushfd ;save flags
Init: lea ecx, OutArray ;load addr of OutArray
add ecx, [ArrayLen] ;ecx points to last digit in array
mov [DigitCount], 0d ;clear digit counter
mov [DecNum], 0d ;clear result
Repeater: mov ebx, 0d ;clear all bytes
mov bl, BYTE PTR[ecx] ;grab first digit
sub ecx, 1d ;ecx points to next digit
mov eax, 1d ;eax equals 1 for multiplication
mov edx, 0d ;clear exponent counter
push ecx ;store digit pointer
mov ecx, 16d ;divisor is 16
Power: cmp edx, [DigitCount] ;check if exponent equals digitCount
je Product ;if so, done multiplying
push edx
mul ecx ;otherwise multiply by 16 again
pop edx
add edx, 1d ;increase counter
jmp Power ;repeat
Product: pop ecx ;restore digit pointer
mul ebx ;multiply power of 16 by digit
add [DecNum], eax ;add to running total
add [DigitCount], 1d ;increase digit number
lea eax, OutArray ;eax holds array location
cmp eax, ecx ;check if we've looped all digits
jle Repeater ;if not, continue looping
Done: popfd ;restore flags
popad ;restore registers
ret
HexToDec ENDP
;****************Near procedure for Binary to Decim**************************
; Given : The address of the integer digit array in the data segment
; Process : Multiply each digit times 2 to the power of the digit number
; and add to the running total
; Return : DecNum--containing decimal number in data segment
;******************************************************************************
BinToDec PROC NEAR32
pushad ;save all registers
pushfd ;save flags
Initb: lea ecx, OutArray ;load addr of OutArray
add ecx, [ArrayLen] ;ecx points to last digit in array
mov [DigitCount], 0d ;clear digit counter
mov [DecNum], 0d ;clear result
Repeaterb: mov ebx, 0d ;clear all bytes
mov bl, BYTE PTR[ecx] ;grab first digit
sub ecx, 1d ;ecx points to next digit
mov eax, 1d ;eax equals 1 for multiplication
mov edx, 0d ;clear exponent counter
push ecx ;store digit pointer
mov ecx, 2d ;divisor is 2
Powerb: cmp edx, [DigitCount] ;check if exponent equals digitCount
je Productb ;if so, done multiplying
push edx
mul ecx ;otherwise multiply by 16 again
pop edx
add edx, 1d ;increase counter
jmp Powerb ;repeat
Productb: pop ecx ;restore digit pointer
mul ebx ;multiply power of 16 by digit
add [DecNum], eax ;add to running total
add [DigitCount], 1d ;increase digit number
lea eax, OutArray ;eax holds array location
cmp eax, ecx ;check if we've looped all digits
jle Repeaterb ;if not, continue looping
Doneb: popfd ;restore flags
popad ;restore registers
ret
BinToDec ENDP
;****************Near procedure for Decimal to Hex**************************
; Given : Decimal number in DecNum in data segment
; Process : Divides number by 16 until 0 is reached. Remainders are popped
; from the stack and displayed as digits
; Return : HexNum--containing hexadecimal number in data segment
;******************************************************************************
DecToHex PROC NEAR32
pushad ;save all registers
pushfd ;save flags
mov eax, [DecNum]
mov ecx, 0d ;clear digit counter
mov ebx, 16d ;set divisor
Divide: mov edx,0h
div ebx ;divide number by 16
push edx ;store remainder
inc ecx ;increment digit counter
cmp eax, 0d
ja Divide ;keep dividing if not 0
Display0: pop eax ;peak at top remainder
cmp eax, 10d ;if it's a letter, display 0 first
push eax ;push it back
jb ShowDigit
lea esi, Zero
call PutChar ;print 0
ShowDigit: pop eax ;pop remainders off stack
cmp eax, 10d ;check whether alpha or numeric
jae AlphaHx
Numbre: or eax, 30h ;subtract number offset
jmp PrintHexChar
AlphaHx: add eax, 37h ;subtract alpha offset
PrintHexChar: mov [HexNum], eax ;store digit
lea esi, HexNum
call PutChar ;display digit
dec ecx ;decrement digit counter
jnz ShowDigit ;continue until zero
popfd ;restore flags
popad
ret
DecToHex ENDP
;****************Near procedure for Decimal to Binary**************************
; Given : Decimal number in DecNum in data segment
; Process : Divides number by 2 until 0 is reached. Remainders are popped
; from the stack and displayed as digits
; Return : BinNum--containing binary number in data segment
;******************************************************************************
DecToBin PROC NEAR32
pushad ;save all registers
pushfd ;save flags
mov eax, [DecNum]
mov ecx, 0d ;clear digit counter
mov ebx, 2d ;set divisor
Divideb: mov edx,0h
div ebx ;divide number by 16
push edx ;store remainder
inc ecx ;increment digit counter
cmp eax, 0d ;continue until result is 0
ja Divideb
ShowDigitb: pop eax ;pop remainders off stack
cmp eax, 10d ;check whether alpha or numeric
jge AlphaHxb
Numbreb: or eax, 30h ;add numeric offset
jmp PrintHexCharb
AlphaHxb: add eax, 37h ;add alpha offset
PrintHexCharb: mov [BinNum], eax ;store digit
lea esi, BinNum
call PutChar ;display digit
dec ecx
jnz ShowDigitb
popfd ;restore flags
popad
ret
DecToBin ENDP
;********************* Near procedure to get a Character **********************
; Given : The Address of the Character to get in ESI register
; Process : Input the Character using the kernel32.lib ReadFile from the
; : Standard_Input function call. No registers are changed and the
; : flags are not affected.
; Return : The input character in the data segment
;******************************************************************************
GetChar PROC NEAR32 ; Define procedure
pushad ; save all registers
pushfd ; save flags
INVOKE GetStdHandle,STD_INPUT ; get handle for keyboard
mov hStdIn, eax ; save the handle
INVOKE SetConsoleMode, ; invoke standard console with
hStdIn, ; file handle for keyboard
ENABLE_PROCESSED_INPUT ; turn line buffering off
INVOKE ReadFile, ; invoke standard ReadFile with
hStdIn, ; file handle for keyboard
esi, ; address of character
1, ; length of one byte
NEAR32 PTR read, ; variable for # bytes read
0 ; overlapped mode
call PutChar ; echo the character on screen
popfd ; restore flags
popad ; restore registers
ret ; return to caller
GetChar ENDP
;******************* NEAR32 procedure to print a Character ********************
; Given : The Address of the Character to print in ESI register
; Process : Print the Character using the kernel32.lib WriteFile to
; : Standard_Output function call. No registers are changed and the
; : flags are not affected.
; Return : Nothing
;******************************************************************************
PutChar PROC NEAR32 ; Define procedure
pushad ; save registers
pushfd ; save flags
INVOKE GetStdHandle,STD_OUTPUT ; get handle for console output
mov hStdOut, eax ; copy file handle for screen
INVOKE SetConsoleMode, ; invoke standard console with
hStdOut, ; file handle for screen
ENABLE_PROCESSED_OUTPUT ; turn line buffering off
INVOKE WriteFile, ; invoke standard WriteFile with
hStdOut, ; file handle for screen
esi, ; address of character
1, ; length of one byte
NEAR32 PTR written, ; variable for # bytes written
0 ; overlapped mode
popfd ; restore flags
popad ; restore registers
ret ; return to caller
PutChar ENDP
;********************* Near procedure to get a String *************************
; Given : The Address of the String to fill in ESI register
; Process : Input the String using the kernel32.lib ReadFile from the
; : Standard_Input function call. No registers are changed and the
; : flags are not affected.
; Return : The input string in the data segment
;******************************************************************************
GetString PROC NEAR32 ; Define procedure
pushad ; save all registers
pushfd ; save flags
INVOKE GetStdHandle,STD_OUTPUT ; get handle for console
mov hStdOut, eax ; save the handle
INVOKE SetConsoleMode, ; invoke standard console with
hStdOut, ; file handle for keyboard
ENABLE_LINE_WRAP ; turn line wrap on
INVOKE GetStdHandle,STD_INPUT ; get handle for console
mov hStdIn, eax ; save the handle
INVOKE SetConsoleMode, ; invoke standard console with
hStdIn, ; file handle for keyboard
DISABLE_PROCESSED_INPUT ; turn line buffering on
mov ecx, MAXSTR ; string length
mov strLength, ecx ; maximum string to accept
mov strAddr, esi ; save pointer to input string
INVOKE ReadFile, ; invoke standard ReadFile with
hStdIn, ; file handle for keyboard
strAddr, ; address of string
strLength, ; length of string
NEAR32 PTR read, ; variable for # bytes read
0 ; overlapped mode
mov ecx, read ; number of bytes read
mov BYTE PTR [esi+ecx-2],0 ; replace CR/LF by trailing null
popfd ; restore flags
popad ; restore registers
ret ; return to caller
GetString ENDP
;******************* NEAR32 procedure to print a string ***********************
; Given : The Address of Null (0) terminated String to print in ESI register
; Process : Print the String using the kernel32.lib WriteFile to
; : Standard_Output function call. No registers are changed and the
; : flags are not affected.
; Return : Nothing
;******************************************************************************
PrintString PROC NEAR32
pushad ; save registers
pushfd ; save flags
mov strAddr, esi ; copy string address
; find string length
mov strLength, 0 ; initialize string length
WhileChar: cmp BYTE PTR [esi], 0 ; character = null?
jz EndWhileChar ; exit if so
inc strLength ; increment character count
inc esi ; point at next character
jmp WhileChar ; while more characters exist
EndWhileChar:
INVOKE GetStdHandle,STD_OUTPUT ; get handle for console output
mov hStdOut, eax ; copy file handle for screen
INVOKE WriteFile, ; invoke standard WriteFile with
hStdOut, ; file handle for screen
strAddr, ; address of string
strLength, ; length of string
NEAR32 PTR written, ; variable for # bytes written
0 ; overlapped mode
popfd ; restore flags
popad ; restore registers
ret ; return to caller
PrintString ENDP
;**************** Procedure to Convert ASCII to Integer ***********************
; Given : A pointer to the string to be Converted in the ESI register and a
; : pointer to the destination integer in EDI
; Process : Convert the string of ASCII digits to an integer and store the
; : string in the address pointed to by EDI. No registers are changed
; : and the flags are not affected.
; Return : Nothing
;******************************************************************************
Ascii2Int PROC NEAR32
pushad ;Save the contents of all registers
pushfd ;
cld ;Set the direction flag for forward
mov ebx,0h ;Zero the EBX register
xor eax,eax ;Clear the EAX register
NextIn: lodsb ;Get a character from the string
cmp al,'0' ;If the character is less than 0, then
jl Done ; we have all the number and are Done
cmp al,'9' ;If the character is more than 9, then
jg Done ; we have all the number and are Done
and al,0Fh ;Mask out the high 4 bits, converting to Int
xor ah,ah ;Zero the high byte of AX
push eax ;Save the digit on the stack
mov eax,10d ;Place 10 decimal in AX to multiply by
mul ebx ;Multiply the number by 10
mov ebx,eax ;Get number from EAX and put in EBX
pop eax ;Get the digit back from the stack
add ebx,eax ;Add the digit to the number
jmp NextIn ;Get the next digit
Done: mov [edi],ebx ;Save NUMBER at address pointed to by EDI
popfd ;Restore the registers
popad ;
ret ;Return to Calling procedure
Ascii2Int ENDP
;**************** Procedure to Convert Integer to ASCII ***********************
; Given : A pointer to the integer to be Converted in the ESI register and a
; : pointer to the destination string in EDI
; Process : Convert the integer to a string of ASCII digits and store the
; : string in the address pointed to by EDI. No registers are changed
; : and the flags are not affected.
; Return : Nothing
;******************************************************************************
Int2Ascii PROC NEAR32
pushad ;Save the contents of all registers
pushfd ;
cld ;Set the direction flag for forward
mov eax,[esi] ;copy the integer to eax
mov ecx,0h ;Zero the CX register for digit counter
mov ebx,10d ;Set up divisor of 10 decimal
NextOut:mov edx,0h ;Zero EDX reg for high order dword of div
div ebx ;Divide number in EAX by 10d
push edx ;Save remainder on the stack
inc ecx ;Count the digit
cmp eax,0h ;Is number in EAX greater than 0
jg NextOut ;Yes, get next digit
CharOut:pop eax ;Get number from the stack
or eax, 0030h ;Convert Int to Ascii by adding 30h
stosb ; and store in the destination string
dec ecx ;Reduce characters to print by one
jnz CharOut ;If CX > 0 loop to print next digit
mov al,0 ;Place a NULL in AL
stosb ; and null terminate the string
popfd ;Restore the registers
popad ;
ret ;Return to Calling procedure
Int2Ascii ENDP
Public _main
END ;Code segment ends
Code: Select all
Welcome to the binary-decimal-hex converter
program. You will enter a number that is either
in binary, hexadecimal, or decimal form, and I
will convert your number into the each of the
other two forms and then print out all three.
In order for me to perform, you must adhere to
the following restrictions:
Binary numbers up to 32 bits
Decimal numbers no greater than 4,294,967,295
Hexadecimal values up to FFFFFFFF
Enjoy.
Enter the number corresponding to the base of your number to be converted.
1) Base 10
2) Base 16
3) Base 2
4) Quit
5
Invalid input. Try again.
Enter the number corresponding to the base of your number to be converted.
1) Base 10
2) Base 16
3) Base 2
4) Quit
1
Enter a decimal number. (less than 4294967295d)
23456
Your number in decimal is: 23456
Your number in hexadecimal is: 5BA0
Your number in binary is: 101101110100000
Enter the number corresponding to the base of your number to be converted.
1) Base 10
2) Base 16
3) Base 2
4) Quit
2
Enter a hexadecimal number. (less than 0FFFFFFFFh)
FFFFFFFFF
Invalid input. Try again.
Enter a hexadecimal number. (less than 0FFFFFFFFh)
FFFFFFFF
Your number in decimal is: 4294967295
Your number in hexadecimal is: 0FFFFFFFF
Your number in binary is: 11111111111111111111111111111111
Enter the number corresponding to the base of your number to be converted.
1) Base 10
2) Base 16
3) Base 2
4) Quit
3
Enter a binary number. (less than 33 digits)
11001010101
Your number in decimal is: 1621
Your number in hexadecimal is: 655
Your number in binary is: 11001010101
Enter the number corresponding to the base of your number to be converted.
1) Base 10
2) Base 16
3) Base 2
4) Quit
- Falco Girgis
- Elysian Shadows Team
- Posts: 10294
- Joined: Thu May 20, 2004 2:04 pm
- Current Project: Elysian Shadows
- Favorite Gaming Platforms: Dreamcast, SNES, NES
- Programming Language of Choice: C/++
- Location: Studio Vorbis, AL
- Contact:
Re: Falco's MSP430 (and now x86) Assembly Programs
Last week's microprocessor lab introduced us to I/O ports. We were required to flash LEDs in a sequence by varying voltage levels via bit manipulation on ports.
We had to do the equivalent in C and assembly.
MSP430 assembly:
C (lol)
We had to do the equivalent in C and assembly.
MSP430 assembly:
Code: Select all
#include <msp430xG46x.h>
NAME main ; module name
PUBLIC main ; make main accessible from outside module
ORG 0FFFEh
DC16 init ; set reset vector to 'init' label
RSEG CSTACK ; pre-declaration of segment CSTACK
RSEG CODE ; place program in 'CODE' segment
init: MOV #SFE(CSTACK), SP ; initialize stack
BIS.B #03h, &P1DIR
BIS.B #30h, &P7DIR
main: MOV.B #00h, &P7OUT
MOV.B #01h, &P1OUT
MOV #50000, R15
wait1: DEC R15
NOP
NOP
JNZ wait1
MOV.B #02, &P1OUT
MOV #050000, R15
wait2: DEC R15
NOP
NOP
JNZ wait2
MOV.B #00h, &P1OUT
MOV.B #10h, &P7OUT
MOV #50000, R15
wait3: DEC R15
NOP
NOP
JNZ wait3
MOV.B #20h, &P7OUT
MOV #50000, R15
wait4: DEC R15
NOP
NOP
JNZ wait4
JMP main
END
Code: Select all
#include "msp430xG46x.h"
int main() {
WDTCTL = WDTPW + WDTHOLD;
P1DIR |= 0x03;
P7DIR |= 0x30;
for(;;) {
volatile int i;
P1OUT = 0x02;
i = 25000;
do { --i; } while (i != 0);
P1OUT = 0x00;
P7OUT = 0x10;
i = 25000;
do { --i; } while ( i != 0);
P7OUT = 0x20;
i = 25000;
do { --i; } while( i!= 0);
P7OUT = 0x00;
}
return 0;
}
Re: Falco's MSP430 (and now x86) Assembly Programs
I downloaded a PDF for x86 ASM in June, I think. I haven't used it though.
Goals for 2009/10
-Learn ASM
-Understand these programs
-Kill Mark Overmars.
Good goals
Goals for 2009/10
-Learn ASM
-Understand these programs
-Kill Mark Overmars.
Good goals
I'm an altogether bad-natured Cupid.