int main() {
int a, b, c, d;
unsigned int ua;
a = 100;
b = a;
//字符串
char say[] = "hello";
scanf("%d,%d", &a, &b);
printf("a=%d,b=%d", a, b);
b = 5;
//加
c = a + b;
printf("c=%d", c);
//减
d = a - b;
printf("d=%d", d);
//乘
c = a * b;
printf("c=%d", c);
//除
d = a / b;
printf("d=%d", d);
}
。
.rodata.str1.1:0000000000000150 $d.1 (命名) DCB "hello",0
.rodata.str1.1:0000000000000156 aDD DCB "%d,%d",0
.rodata.str1.1:000000000000015C aADBD DCB "a=%d,b=%d",0
.rodata.str1.1:0000000000000166 aCD DCB "c=%d",0
.rodata.str1.1:000000000000016B aDD_0 DCB "d=%d",0
DCB 表示一个字节,可以通过右键设置数据类型。
DBW表示双字节,即一个字。还有double word等。字符串在C语言中以0结尾。
.rodata:000020E8 aHello DCB "hello",0
//aHello,命名。DCB表示一个字节;B为byte,还有word,double word等。分配的不一定是正确的。该句表示定义一个字符串,hello,命令为aHello。aHello=”hello“
.rodata:000020EE aDD DCB "%d,%d",0 ; DATA XREF: main+2Ao
.rodata:000020EE ; .text:off_870o
//aDD,命名。DCB同理。
//该句可以理解为aDD=”%d,%d”;后面的DATA XREF是交叉编译,表示引用的位置。
//两行相同的地址,是ida做一个信息补充的作用
.text:000007A8 CODE16
//指令集,16位,2个字节。
//代码段中的分号”;”表示注释
//LB,LBX表示调用方法
//STR写数据到内存
//LDR从内存中读取数据
//SUBS 表示除法
//MULS表示乘
//BL __divsi3 调用除法
.text:000007A8 PUSH {R7,LR}
.text:000007AA MOV R7, SP
.text:000007AC SUB SP, SP, #0x48
.text:000007AE LDR R0, =(__stack_chk_guard_ptr - 0x7B4)
.text:000007B0 ADD R0, PC ; __stack_chk_guard_ptr
.text:000007B2 LDR R0, [R0] ; __stack_chk_guard
.text:000007B4 LDR R1, [R0]
.text:000007B6 STR R1, [SP,#0x50+var_C]
.text:000007B8 MOVS R1, #0x64
//MOVS ,移动0x64到R1;对应C代码中的a=100
.text:000007BA STR R1, [SP,#0x50+var_18]
//STR将寄存器R1的内容写入内存中。
//[xxx]寻址操作,表示地址:sp+(0x50+var_18)
.text:000007BC LDR R1, [SP,#0x50+var_18]
//LDR表示定位一个全局资源
.text:000007BE STR R1, [SP,#0x50+var_1C]
.text:000007C0 MOVS R1, #0x6F
.text:000007C2 STRH.W R1, [SP,#0x50+var_10]
.text:000007C6 MOV R1, #0x6C6C6568
.text:000007CE STR R1, [SP,#0x50+var_14]
scanf(“%d,%d”,&a,&b);
.text:000007D0 LDR R1, =(aDD - 0x7D6)
.text:000007D2 ADD R1, PC ; "%d,%d"
//LDR+ADD,该句表示R1指向了”%d,%d”字符串,
.text:000007D4 ADD R2, SP, #0x50+var_18
//ADD三个参数,表示R2=SP+第三个参数;这里是取地址,
//对应C中的&a
.text:000007D6 ADD R3, SP, #0x50+var_1C
//取地址,对应C语言中的&b
.text:000007D8 STR R0, [SP,#0x50+var_2C]
//STR:写入内存
.text:000007DA MOV R0, R1 ; format
.text:000007DC MOV R1, R2
.text:000007DE MOV R2, R3
.text:000007E0 BLX scanf
//scanf(“%d,%d”,&a,&b);
//通过07DA-07E0分析,scanf的参数有R0,R1,R2,其中R0的值由R1赋,即“%d,%d”,同理推出scanf(“%d,%d”,&a,&b)这一段代码。
question:我怎么知道这个函数需要几个参数
answer:一般是由R0-R3来传递前四个参数。四个以上暂时不知道。
printf(“a=%d,b=%d”,a,b)
.text:000007E4 LDR R1, [SP,#0x50+var_18]
//LDR:从内存中加载数据
.text:000007E6 LDR R2, [SP,#0x50+var_1C]
.text:000007E8 LDR R3, =(aADBD - 0x7EE)
.text:000007EA ADD R3, PC ; "a=%d,b=%d"
//R3指向了字符串” a=%d,b=%d"
.text:000007EC STR R0, [SP,#0x50+var_30]
.text:000007EE MOV R0, R3 ; format
.text:000007F0 BLX printf
//RO对应参数是字符串xxx,R1和R2在E4,E6分别取值
//printf(“a=%d,b=%d”,a,b)
b=5;c=a+b;printf c
.text:000007F4 MOVS R1, #5
// R1=5,对应b=5
.text:000007F6 STR R1, [SP,#0x50+var_1C]
//b的地址为0X50+VAR_1C
.text:000007F8 LDR R1, [SP,#0x50+var_18]
//加载a的数据到R1
.text:000007FA LDR R2, [SP,#0x50+var_1C]
//加载b的数据到R2
.text:000007FC ADD R1, R2
//R1=R1+R2
.text:000007FE STR R1, [SP,#0x50+var_20]
//将R1的值赋给0x50+var_20
.text:00000800 LDR R1, [SP,#0x50+var_20]
//加载值R1=c
.text:00000802 LDR R2, =(aCD - 0x808)
.text:00000804 ADD R2, PC ; "c=%d"
//加载字符串
.text:00000806 STR R0, [SP,#0x50+var_34]
.text:00000808 MOV R0, R2
//R0=”c=%d”
.text:0000080A STR R2, [SP,#0x50+format]
.text:0000080C BLX printf
//printf(“c=%d”,c)
question:赋值R2的意义在哪里,因为R2,R3都没有用到
.text:00000810 LDR R1, [SP,#0x50+var_18]
.text:00000812 LDR R2, [SP,#0x50+var_1C]
.text:00000814 SUBS R1, R1, R2
.text:00000816 STR R1, [SP,#0x50+var_24]
.text:00000818 LDR R1, [SP,#0x50+var_24]
.text:0000081A LDR R2, =(aDD_0 - 0x820)
.text:0000081C ADD R2, PC ; "d=%d"
.text:0000081E STR R0, [SP,#0x50+var_3C]
.text:00000820 MOV R0, R2 ; format
.text:00000822 STR R2, [SP,#0x50+var_40]
.text:00000824 BLX printf
.text:00000828 LDR R1, [SP,#0x50+var_18]
.text:0000082A LDR R2, [SP,#0x50+var_1C]
.text:0000082C MULS R1, R2
.text:0000082E STR R1, [SP,#0x50+var_20]
.text:00000830 LDR R1, [SP,#0x50+var_20]
.text:00000832 LDR R2, [SP,#0x50+format]
.text:00000834 STR R0, [SP,#0x50+var_44]
.text:00000836 MOV R0, R2 ; format
.text:00000838 BLX printf
.text:0000083C LDR R1, [SP,#0x50+var_18]
.text:0000083E LDR R2, [SP,#0x50+var_1C]
.text:00000840 STR R0, [SP,#0x50+var_48]
.text:00000842 MOV R0, R1
.text:00000844 MOV R1, R2
.text:00000846 BL __divsi3
.text:0000084A STR R0, [SP,#0x50+var_24]
.text:0000084C LDR R1, [SP,#0x50+var_24]
.text:0000084E LDR R0, [SP,#0x50+var_40] ; format
.text:00000850 BLX printf
.text:00000854 LDR R1, [SP,#0x50+var_2C]
.text:00000856 LDR R2, [R1]
.text:00000858 LDR R3, [SP,#0x50+var_C]
.text:0000085A CMP R2, R3
.text:0000085C STR R0, [SP,#0x50+var_4C]
.text:0000085E BNE loc_868
.text:00000860 B loc_862
.text:00000862 ; ---------------------------------------------------------------------------
.text:00000862
.text:00000862 loc_862 ; CODE XREF: main+B8j
.text:00000862 MOVS R0, #0
.text:00000864 ADD SP, SP, #0x48
.text:00000866 POP {R7,PC}
.text:00000868 ; ---------------------------------------------------------------------------
.text:00000868
.text:00000868 loc_868 ; CODE XREF: main+B6j
.text:00000868 BLX __stack_chk_fail
.text:00000868 ; End of function main
总结:
- 在这个简单的加减乘除读写中,过程无非是读内存值---取内存值---运算---写入内存---执行输出函数
- 留意寄存器变量的值从哪里得到,一层一层得到一个不可变的值,最终就能得到该寄存器的最终值
- 留意各个变量的地址。变量在汇编中几乎都是以地址的方式出现,不好确定。