DChilders84 said:ASM is a procedural language. You're not going to see ifs or loops in ASM, at least not like you'd be familiar with from a high-level language.
DChilders84 said:ASM is a procedural language. You're not going to see ifs or loops in ASM, at least not like you'd be familiar with from a high-level language.
if(variable == 2){
//stuff to do when variable == 2
}
lda variable;Copy the value of variable into a convenient place to check it (the accumulator)
cmp #2;CoMPare the value in the accumulator to the number 2.
bne variableisnottwo;Branch if Not Equal to skip the code that should only be run when the variable is equal to two
;Stuff to do when variable == 2
variableisnottwo:
for(int x = 0; x < 10; x++){
//Stuff to do 10 times
}
ldx #0;Copy the number 0 into X. One can easily subtract one from or add one to X, as well as access data X bytes away from a given address.
loop:
//stuff to do 10 times
inx;Add one to X. INcrement X.
cpx #10;You want to do 0-9, but not 10 so when the add makes X equal to 10, we don't want to loop,
;CPX is like CMP in the if statement example. Except it CoMpares X to the given value instead of comparing the accumulator to the given value.
bne loop;If X has not yet reached 10, we want to run the loop again
ldx #10;The number of times you want to loop
loop:
//stuff to do 10 times
dex;Subtract one from X. DEcrement X.
bne loop
for(int x = 10; x >0; x--){
}
for(int x = 0; x < 10; x++){
}
for(int x = 0; x < 0; x++){
//This code would never run because zero is not less than zero
}
ldx #0
loop:
//Stuff to do zero times. Except. It'd run WAY more than zero times
inx;X was zero in the first iteration. Now it's 1, so we actually loop again. Then again for 2, and 3 and 255 until we get back to zero.
cpx #0;Technically not needed because inx automatically checks for zero. But the code is still broken.
bne loop
while(variable == 20){
//code here
}
loop:
lda variable;
cmp #20;If variable is not equal to 20
bne endloop;don't run the loop
;code here
jmp loop;Jump is a non conditional branch. We return to the conditional check.
endloop:
lda variable;
cmp #20;If variable is not equal to 20
bne endloop;don't run the loop
loop:
;Code here
lda variable;
cmp #20;If variable IS equal to 20
beq loop;continue to loop. BNE was branch if not equal. BEQ is Branch if EQual.
endloop:
while(true){
;code here
}
loop:
;code here
jmp loop
Kasumi said:No need to be rude.
IF / ELSEIF / ELSE / ENDIF
Process a block of code if an expression is true (nonzero).
IF j>0
DB i/j
ELSE
DB 0
ENDIF
;Get volume envelopes address.
ldy #0
lda (sound_param_word_2),y
sta base_address_volume_envelopes
iny
lda (sound_param_word_2),y
sta base_address_volume_envelopes+1
ifdef FEATURE_ARPEGGIOS
;Get arpeggio envelopes address.
iny
lda (sound_param_word_2),y
sta base_address_arpeggio_envelopes
iny
lda (sound_param_word_2),y
sta base_address_arpeggio_envelopes+1
endif
MACRO setAXY x,y,z
LDA #x
LDX #y
LDY #z
ENDM
setAXY $12,$34,$56
;expands to LDA #$12
; LDX #$34
; LDY #$56
MACRO ifgreaterthanunsigned x, y, z
;Macro definition here
ENDM
ifgreaterthanunsigned variable, #2, endblock
;Code to run if variable is > 2
endblock:
Kasumi said:That's for conditionally assembling things, Mihoshi20. If the condition is true, the code ends up in your program.If the condition is false,the code does not end in your program.
GGSound uses them to disable features. (This saves space and RAM over having bytes in the program for features the user isn't using.)
If FEATURE_ARPEGGIOS is defined, all the code under "Get arpeggio envelopes address." is included. If it is not defined, all the code under "Get arpeggio envelopes address." is not included. The program becomes at least 10 bytes shorter.Code:;Get volume envelopes address. ldy #0 lda (sound_param_word_2),y sta base_address_volume_envelopes iny lda (sound_param_word_2),y sta base_address_volume_envelopes+1 ifdef FEATURE_ARPEGGIOS ;Get arpeggio envelopes address. iny lda (sound_param_word_2),y sta base_address_arpeggio_envelopes iny lda (sound_param_word_2),y sta base_address_arpeggio_envelopes+1 endif
Basically it gives the power to remove the code itself, rather than just not running it. If it's not there, it can't be run ever. Whatever ends up running the code never sees anything related to the if statement. These if statements are information only for the assembler.
Edit: I know a few developers who created if statements using assembler macros, though.
This is an example of macros from asm6 documentation.
So you could create a macro likeCode:MACRO setAXY x,y,z LDA #x LDX #y LDY #z ENDM setAXY $12,$34,$56 ;expands to LDA #$12 ; LDX #$34 ; LDY #$56
Where X is the value you want to see if it's greater than Y, and Z is the label where the block ends.Code:MACRO ifgreaterthanunsigned x, y, z ;Macro definition here ENDM
And then in your code you could do
But what the macro definition itself would look like, I'd have to do some testing. I'm not sure if/how one can determine the addressing mode of a value given as an argument in an asm6 macro which affects what code would need to be generated by the macro.Code:ifgreaterthanunsigned variable, #2, endblock ;Code to run if variable is > 2 endblock:
You'd need to create a macro for every type of conditional you want, though. (ifgreaterthansigned, ifgreaterthansigned16bit, ifgreaterthanunsigned, ifgreaterthansigned16bit, ifgreaterthanorequalsigned....) etc. (Or maybe add additional parameters to each that allow choosing of the type of the actual comparison.)
lda #-1;Assembles as $A9 $FF
lda #255;Also assembles as $A9 $FF
lda #-1;Load the accumulator with -1
cmp #255;Compare to 255
bne label;If the two numbers were not equal, skip
lda #2;Will this line of code run?
label:
lda #-1
sta variable
lda #0
sta variable2
if variable > variable2
lda #2;Should this run or not?
endif
char variable = -1;
unsigned char variable2 = 255;
switch( variable ){
case 26:
break;
case 44:
break;
case 127:
break;
case 250:
break;
}
switch( variable ){
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
}
; Jumps to the subroutine indexed by 'A'.
do_action:
asl
tax
lda table,x
sta ptr
lda table+1,x
sta ptr+1
jmp (ptr)
postswitch:
rts
table:
.dw case1
.dw case2
case1:
;code for case 1 here
jmp postswitch
case2:
;code for case 2 here
jmp postswitch
table_lo:
.dl case1
.dl case2
table_hi:
.dh case1
.dh case2
; Jumps to the subroutine indexed by 'A'.
do_action:
tax
lda table_lo,x
sta ptr
lda table_hi,x
sta ptr+1
jmp (ptr)
postswitch: