[TI ASM] Make a simple program

Got questions? Got answers? Go here for both.

Moderator: MaxCoderz Staff

Post Reply
User avatar
Wesley
Regular Member
Posts: 137
Joined: Sun 12 Oct, 2008 1:42 am
Location: Boise, Idaho
Contact:

[TI ASM] Make a simple program

Post by Wesley »

I'm studying ASM and having no knowledge of programming except TI-Basic is a bit difficult. I'm learning from the "Learn ASM in 28 Days" tutorial, but it doesn't have enough example programs for me to understand everything that's happening exactly.
I want to know how a simple basic program will look in ASM. I want to do a simple calculation by retrieving a value from the user and outputting that value^2. Here is a program in TI-Basic:

Code: Select all

:ClrHome    ;Clears the home screen
:Input "Variable=?",A    ;Retrieves value from user and stores it into A
:A^2->A    ;Stores A squared into A
:ClrHome
:Output(1,1,"(Variable)^2=")    ;Displays text in the upper left corner of the screen
:Output(2,1,A)    ;Displays the value of A just under "(Variable)^2="
:Stop    ;Quits the program
I added some comments, though it is very easy to understand what the program does. This is just a habit of mine in programming. I like to know exactly what is happening each step of the way, so if I leave a project, I can come back to it a year later and understand exactly what I was doing.
If you happen to provide me with some code, please comment it at your best. Thank you.
ImageImage
ImageImage
Image
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Re: [TI ASM] Make a simple program

Post by benryves »

Unfortunately, the program you have suggested is not simple to convert to assembly for a number of reasons. Text input is comparatively difficult; you need to create an input loop that polls the keypad, updating a buffer in memory when input is received and displaying the entered text on the display as you go. Once that's done, you need to convert from a text string into a number, which has to be done manually. Now you've done that, to square the value you need to multiply A by itself, not an easy task as the Z80 can't multiply or divide natively. Finally you need to convert the number back into a string to display it.

A simplified version of the program may be this:

Code: Select all

CurrentValue = saveSScreen ; saveSScreen = 768 bytes of free memory.

Main:

	bcall(_ClrLcdFull)  ; Clear the LCD.

	xor a               ; a eor a = 0
	ld (CurrentValue),a ; Set "CurrentValue" to a, ie 0.

ProgramLoop:
	
	; In our loop, first thing we need to do is display the running status.
	
	xor a \ ld (CurCol),a ; Set column to 0.
	xor a \ ld (CurRow),a ; Set row to 0.
	ld hl,VariablePrompt  ; HL = pointer to "Variable=?" prompt string.
	bcall(_PutS)
	
	ld a,(CurrentValue)   ; Load the CurrentValue into A.
	ld h,0                ; Copy the CurrentValue into HL.
	ld l,a                ;
	
	bcall(_DispHL)        ; Display the value of HL.


	xor a \ ld (CurCol),a ; Set column to 0.
	inc a \ ld (CurRow),a ; Set row to 1.
	ld hl,AnswerPrompt    ; HL = pointer to "Variable²=" string.
	bcall(_PutS)
	
	ld a,(CurrentValue)   ; Load the CurrentValue into A.
	ld b,a                ; Copy the CurrentValue into B.
	call SquareB          ; Compute B² (result ends up in HL).
	
	bcall(_DispHL)        ; Display the value of HL.
	
	bcall(_NewLine)       ; Move cursor onto next line.

WaitKeyLoop:	
	bcall(_GetCSC)     ; Get a key.
	or a               ; Is it 0?
	jr z,WaitKeyLoop   ; Yes, so jump back to WaitKeyLoop.
	cp skClear         ; Is it Clear?
	ret z              ; If so, quit the program.
	
	ld hl,CurrentValue ; HL is a pointer to the current value.

	cp skUp            ; Is it Up?
	jr nz,NotUp        ; If not, jump to NotUp
	inc (hl)           ; If we get here (ie, Up was pressed) increment the value at HL.
	jr ProgramLoop     ; Jump back to the main program loop.
NotUp:
	
	cp skDown          ; Is it Down?
	jr nz,NotDown      ; If not, jump to NotDown
	dec (hl)           ; If we get here (ie, Down was pressed) decrement the value at HL.
	jr ProgramLoop     ; Jump back to the main program loop.
NotDown:
	
	jr WaitKeyLoop     ; Loop back to WaitKeyLoop

SquareB: ; Routine that computes B² and stores the value in HL.

	; This is a very naïve implementation!
	; It squares A by adding it to HL B times.
	
	ld hl,0 ; Running total.

	; First: is B zero? If so, quit.
	ld a,b ; Copy B to A.
	or a   ; If A was 0, Z flag is set.
	ret  z ; Exit routine if Z flag is set.
	
	ld d,0 ; Set DE to = B.
	ld e,b ;

SquareBLoop:
	add hl,de
	djnz SquareBLoop ; Loop around to SquareBLoop until B = 0
	
	ret ; We're done!

VariablePrompt: .db "Variable=? ", 0
AnswerPrompt:   .db "Variable", LSquare, "= ", 0
Rather than prompt for text input, it only lets the user press up or down to increment or decrement a value. It is also limited to handling 8-bit integral input values.
User avatar
Wesley
Regular Member
Posts: 137
Joined: Sun 12 Oct, 2008 1:42 am
Location: Boise, Idaho
Contact:

Re: [TI ASM] Make a simple program

Post by Wesley »

Wow, I didn't expect that much code to come out, but it makes sense now that you show it to me. Anyway, did you run the Basic version on your calculator? I think some of the ASM could be shortened a bit - can't you get rid of the NotDown label altogether and use jr nz,WaitKeyLoop? Also, to make it more like the Basic version, you don't need as many loops; this will also shorten the program.
Also, the reason you can't make it as easily as the Basic version is because to make the program calculate 0-9 on the keypad, you'd have to make loops to tell the calculator if 0-9 was pressed and then to use the corresponding number. Correct?
Back to your first comment. Actually, this was a pretty easy and simplified use of ASM; the stuff in the tutorial and the source I've looked at in a lot of programs are crazy in comparison. This was great! If I had an ASM version of every TI-Basic program I've made, I could easily understand ASM and how to use it. You see, the ASM code you gave me has the comments and allows me to know what exactly each command is doing.

From your code I was able to understand the following:
-what the incrementing and decrementing functions do,
-how to use variables,
-a little more knowledge of flags and their importance,
-how exactly to use the jr loop command,
-how to use the cp command in correspondence with key detection,
-exactly know what b_call functions can do,
-what call is used for.

What I still don't understand:
-the xor command and what its exact function is (does it set a to 0?),
-the or command and what its exact function is (does it just check if the value is 0?)
-how exactly the multiplication was done (I read this part in the tutorial, but it's still sketchy. Why is "add" significant here? What would be the difference between squaring something and cubing it - in code form).

I think that pretty much sums it up. Thank you. Man, that's really starting to help.
ImageImage
ImageImage
Image
User avatar
benryves
Maxcoderz Staff
Posts: 3087
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Re: [TI ASM] Make a simple program

Post by benryves »

First up, I suggest you download a copy of the Z80 user manual as well as the TI-83+ SDK documentation.
Wesley wrote:Anyway, did you run the Basic version on your calculator? I think some of the ASM could be shortened a bit - can't you get rid of the NotDown label altogether and use jr nz,WaitKeyLoop? Also, to make it more like the Basic version, you don't need as many loops; this will also shorten the program.
True on the first count, but the reason the code does what it does is that I felt it was the easiest way in assembly. A single statement in the calculator's built-in language can end up running a routine that is hundreds of lines long in assembly. On the flip side, there are many things you can do in assembly that are impossible (or very difficult) in the built-in programming language. The two different languages do things quite differently, so being able to translate one to the other is not practical. In a best-case scenario, converting from the built-in programming language to assembly will result in a very large assembly file that contains little more than bcalls to replicate the functionality of the orignal keywords.
What I still don't understand:
-the xor command and what its exact function is (does it set a to 0?),
-the or command and what its exact function is (does it just check if the value is 0?)
XOR (EOR if you're British like me) and OR are both bitwise operators; their exact operation is documented in the Z80 user manual. Using XOR A to set A to zero is a trick to reduce program size and time (XOR A is one byte, LD A,0 is two); OR A to check if a value is zero is a similar trick.
-how exactly the multiplication was done (I read this part in the tutorial, but it's still sketchy. Why is "add" significant here? What would be the difference between squaring something and cubing it - in code form).
The Z80 can't multiply, so the way I've done it is extremely naïve (but simple):

Code: Select all

int multiply(int a, int b) {
    int result = 0;
    for (int i = 0; i < a; ++i) {
        result += b;
    }
    return result;
}
That is to say, 3*5 ends up being calculated as 3+3+3+3+3.
User avatar
Wesley
Regular Member
Posts: 137
Joined: Sun 12 Oct, 2008 1:42 am
Location: Boise, Idaho
Contact:

Re: [TI ASM] Make a simple program

Post by Wesley »

First up, I suggest you download a copy of the Z80 user manual as well as the TI-83+ SDK documentation.
Wow, thanks. These will help a lot. I just wish I could get a hard copy of them, no way would I print them off, but a book would be nice...
ImageImage
ImageImage
Image
Post Reply