装配式制作开关、外壳结构
Make switch, case structure in assembly
如何在汇编程序中制作switch、case结构?什么是正确的或更正确的方法?
这是我用C写的代码,我想用汇编写的。
if (diode_on == 1)
{
switch(diode_num)
{
case 0:
//score += 3;
break;
case 1:
//score += 3;
break;
case 2:
//score += 3;
break;
case 3:
//score += 3;
break;
default:
break;
}
diode_on = 0;
}
我的项目 MMSP430F5XX 需要这个。该项目的条件是一个中断例程是用汇编语言编写的。这是在 C 中打破例程的代码,我尝试用汇编语言编写。
#pragma vector=PORT2_VECTOR
__interrupt void port2handler(void)
{
__delay_cycles(1000);
if (diode_on == 1)
{
switch(diode_num)
{
case 0:
if((P2IFG & BIT4)!=0)
{
if ((P2IN & BIT4)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
case 1:
if((P2IFG & BIT5)!=0)
{
if ((P2IN & BIT5)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
case 2:
if((P2IFG & BIT6)!=0)
{
if ((P2IN & BIT6)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
case 3:
if((P2IFG & BIT7)!=0)
{
if ((P2IN & BIT7)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
default:
break;
}
P4OUT &= ~(BIT3 | BIT4 | BIT5 | BIT6); //gasimo diode
diode_on = 0;
}
P2IFG &= ~(BIT4 | BIT5 | BIT6 | BIT7); // brisanje flega
}
编译时你看到了什么?你的编译器是怎么解决的?
我想到了三种简单的方法来实现这一点,但并非所有方法都可以使用。首先也是最重要的是,if-then-else 树将始终有效,并且根据您的案例值有时是唯一明智的方法。
除此之外的所有其他内容都是 "it depends" 例如,您删除了您的评论并且您希望 0,1,2,3 将分数加三,而所有其他值不是...AND。 ..diode_num 可以是这些数字中的任何一个或其他值,例如 75。甚至 4。那么您 could/implement 就是:
if(diode_num&3) goto skip;
score+=3;
skip:
当然是在 C 中(如果您愿意,可以不使用 goto)或在您的汇编语言的语法中,无论目标是什么。
如果您提供的代码使得 diode_num 只能是 0,1,2,3 那么这不是死代码,但它会针对所有情况优化到 score+=3 并且开关会打开离开。
假设情况并非如此,另一个 "it depends" 是一个跳转 table 这不仅取决于您的案例值,还取决于指令集并取决于可能出现的所有可能值例如,在您提供的代码之外,假设您实际上为每种情况做了一些事情,因为您提供的代码大部分是死代码,它变成了
if(diode_on == 1) diode_on = 0;
你应该提供一个更好的例子。但是如果编译器和优化器可以看到你没有提供的代码,假设发现 diode_num 的可能值范围是 0-7,你想对 0,1,2,3 中的每一个做一些特殊的事情在您未指定的指令集中可以跳转 table,然后
load some_register,table_base_add
shift_left temp_register,diode_num,2 ;assuming 32 bit addresses
add some_register,temp_register
load another_register,[some_register]
branch_to another_register
table_base_add: .word table_base
.align
;jump table
table_base:
.word case0
.word case1
.word case2
.word case3
.word switch_end
.word switch_end
.word switch_end
.word switch_end
;case 0 code
case0:
do something
b switch_end
;case 1 code
case1:
do something
b switch_end
;case 2 code
case2:
do something
b switch_end
;case 3 code
case3:
do something
b switch_end
switch_end:
code after switch
如果编译器无法确定输入值的范围,它可能会或可能不会选择尝试跳转 table。
你可以让它更优化,假设 diode_num 的范围是严格的 0,1,2,3 并且你想为每种情况做一些不同的事情,但这非常简单,在这个如果我使用固定大小的指令进行进一步优化。
load some_register,base_add
shift_left temp_register,diode_num,4
add some_register,temp_register
branch_to some_register
base_add: .word base
base:
;case 0 code
one instruction
b switch_end
nop
nop
;case 1 code
one instruction
one instruction
one instruction
b switch_end
;case 2 code
one instruction
one instruction
b switch_end
nop
;case 3 code
one instruction
nop
nop
b switch_end
switch_end:
在这种情况下,假设每个案例有 16 个字节(四个 32 位字),您只需将 or 或案例乘以 16 到基地址并跳转到那里,不需要跳转 table 只需要数学。如果案例是 1、2、3、4,你可以减去 1,然后乘以 16(左移 4),然后添加到基数并跳转到那里。
既然你是优化编译器,那么你总是可以使用 if then else 树来实现它,或者如果你更了解输入范围的细节、案例数量、每个案例的代码量(这是你应该编码并围绕它构建骨架的第一件事)和指令集,然后你可以优化。
如何在汇编程序中制作switch、case结构?什么是正确的或更正确的方法?
这是我用C写的代码,我想用汇编写的。
if (diode_on == 1)
{
switch(diode_num)
{
case 0:
//score += 3;
break;
case 1:
//score += 3;
break;
case 2:
//score += 3;
break;
case 3:
//score += 3;
break;
default:
break;
}
diode_on = 0;
}
我的项目 MMSP430F5XX 需要这个。该项目的条件是一个中断例程是用汇编语言编写的。这是在 C 中打破例程的代码,我尝试用汇编语言编写。
#pragma vector=PORT2_VECTOR
__interrupt void port2handler(void)
{
__delay_cycles(1000);
if (diode_on == 1)
{
switch(diode_num)
{
case 0:
if((P2IFG & BIT4)!=0)
{
if ((P2IN & BIT4)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
case 1:
if((P2IFG & BIT5)!=0)
{
if ((P2IN & BIT5)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
case 2:
if((P2IFG & BIT6)!=0)
{
if ((P2IN & BIT6)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
case 3:
if((P2IFG & BIT7)!=0)
{
if ((P2IN & BIT7)==0)
//score += 3;
calculationScore(3);
}
else
//score--;
calculationScore(-1);
break;
default:
break;
}
P4OUT &= ~(BIT3 | BIT4 | BIT5 | BIT6); //gasimo diode
diode_on = 0;
}
P2IFG &= ~(BIT4 | BIT5 | BIT6 | BIT7); // brisanje flega
}
编译时你看到了什么?你的编译器是怎么解决的?
我想到了三种简单的方法来实现这一点,但并非所有方法都可以使用。首先也是最重要的是,if-then-else 树将始终有效,并且根据您的案例值有时是唯一明智的方法。
除此之外的所有其他内容都是 "it depends" 例如,您删除了您的评论并且您希望 0,1,2,3 将分数加三,而所有其他值不是...AND。 ..diode_num 可以是这些数字中的任何一个或其他值,例如 75。甚至 4。那么您 could/implement 就是:
if(diode_num&3) goto skip;
score+=3;
skip:
当然是在 C 中(如果您愿意,可以不使用 goto)或在您的汇编语言的语法中,无论目标是什么。
如果您提供的代码使得 diode_num 只能是 0,1,2,3 那么这不是死代码,但它会针对所有情况优化到 score+=3 并且开关会打开离开。
假设情况并非如此,另一个 "it depends" 是一个跳转 table 这不仅取决于您的案例值,还取决于指令集并取决于可能出现的所有可能值例如,在您提供的代码之外,假设您实际上为每种情况做了一些事情,因为您提供的代码大部分是死代码,它变成了
if(diode_on == 1) diode_on = 0;
你应该提供一个更好的例子。但是如果编译器和优化器可以看到你没有提供的代码,假设发现 diode_num 的可能值范围是 0-7,你想对 0,1,2,3 中的每一个做一些特殊的事情在您未指定的指令集中可以跳转 table,然后
load some_register,table_base_add
shift_left temp_register,diode_num,2 ;assuming 32 bit addresses
add some_register,temp_register
load another_register,[some_register]
branch_to another_register
table_base_add: .word table_base
.align
;jump table
table_base:
.word case0
.word case1
.word case2
.word case3
.word switch_end
.word switch_end
.word switch_end
.word switch_end
;case 0 code
case0:
do something
b switch_end
;case 1 code
case1:
do something
b switch_end
;case 2 code
case2:
do something
b switch_end
;case 3 code
case3:
do something
b switch_end
switch_end:
code after switch
如果编译器无法确定输入值的范围,它可能会或可能不会选择尝试跳转 table。
你可以让它更优化,假设 diode_num 的范围是严格的 0,1,2,3 并且你想为每种情况做一些不同的事情,但这非常简单,在这个如果我使用固定大小的指令进行进一步优化。
load some_register,base_add
shift_left temp_register,diode_num,4
add some_register,temp_register
branch_to some_register
base_add: .word base
base:
;case 0 code
one instruction
b switch_end
nop
nop
;case 1 code
one instruction
one instruction
one instruction
b switch_end
;case 2 code
one instruction
one instruction
b switch_end
nop
;case 3 code
one instruction
nop
nop
b switch_end
switch_end:
在这种情况下,假设每个案例有 16 个字节(四个 32 位字),您只需将 or 或案例乘以 16 到基地址并跳转到那里,不需要跳转 table 只需要数学。如果案例是 1、2、3、4,你可以减去 1,然后乘以 16(左移 4),然后添加到基数并跳转到那里。
既然你是优化编译器,那么你总是可以使用 if then else 树来实现它,或者如果你更了解输入范围的细节、案例数量、每个案例的代码量(这是你应该编码并围绕它构建骨架的第一件事)和指令集,然后你可以优化。