脑袋抽筋,忽而觉得很少留意STMFD、LDMFD指令,于是反汇编一个简单程序观察其用法。
手册给出的说法是:
STMFD SP!,{R0-R7,LR}
手册给出的说法是:
STMFD SP!,{R0-R7,LR}
SP = SP - 9×4;
address = SP;
for i = 0 to 7
Memory[address] = Ri;
address = address + 4;
Memory[address] = LR;
也就是,最终栈顶SP指向的是R0,如果直接取栈顶的元素,得到的是最先入栈的数据。大概不能用数据结构中“栈”的概念来套用这种行为,只要STMFD与LDMFD成对使用就行了。
int main()
{
int ret = isIfceExist("192.168.0.3");
return ret;
}
ARM Linux G++ 4.3.2 版本 O1优化级别时,IDA 6.4给出的结果如下:
.text:00008B1C EXPORT main
.text:00008B1C main ; DATA XREF: .text:000085E0o
.text:00008B1C ; .text:off_85F4o
.text:00008B1C
.text:00008B1C var_8 = -8
.text:00008B1C
.text:00008B1C 00 48 2D E9 STMFD SP!, {R11,LR}
.text:00008B20 04 B0 8D E2 ADD R11, SP, #4 ;将LR内存副本的地址存入R11
.text:00008B24 08 D0 4D E2 SUB SP, SP, #8 ;开辟8字节临时堆栈空间
.text:00008B28 18 00 9F E5 LDR R0, =aWoca ; "192.168.0.3" 传递参数
.text:00008B2C B8 FF FF EB BL _ZL11isIfceExistPKc ; isIfceExist(char const*) 调用函数
.text:00008B30 00 30 A0 E1 MOV R3, R0 ;返回值转存于R3
.text:00008B30 00 30 A0 E1 MOV R3, R0 ;返回值转存于R3
.text:00008B34 08 30 0B E5 STR R3, [R11,#var_8] ;临时变量,即SP-4位置
.text:00008B38 08 30 1B E5 LDR R3, [R11,#var_8] ;
.text:00008B3C 03 00 A0 E1 MOV R0, R3 ;main()函数的返回值
.text:00008B38 08 30 1B E5 LDR R3, [R11,#var_8] ;
.text:00008B3C 03 00 A0 E1 MOV R0, R3 ;main()函数的返回值
.text:00008B40 04 D0 4B E2 SUB SP, R11, #4 ;恢复SP,收回临时分配的8字节堆栈空间
.text:00008B44 00 88 BD E8 LDMFD SP!, {R11,PC} ;main()函数返回
.text:00008B44 ; End of function main
.text:00008B44 00 88 BD E8 LDMFD SP!, {R11,PC} ;main()函数返回
.text:00008B44 ; End of function main
O3优化级别时,就很简洁了:
.text:00008674 EXPORT main
.text:00008674 main ; DATA XREF: .text:00008480o
.text:00008674 ; .text:off_8494o
.text:00008674 00 00 9F E5 LDR R0, =aWoca ; "woca"
.text:00008678 A3 FF FF EA B _ZL11isIfceExistPKc ; isIfceExist(char const*)
.text:00008678 ; End of function main
.text:00008678
.text:00008678 ; ---------------------------------------------------------------------------
.text:0000867C 78 87 00 00 off_867C DCD aWoca ; DATA XREF: mainr
.text:0000867C ; "woca"
isIfceExist(const char *ifceName)源码:
.text:0000850C ; isIfceExist(char const*)
.text:0000850C _ZL11isIfceExistPKc ; CODE XREF: main+4j
.text:0000850C
.text:0000850C in = -0x204
.text:0000850C var_1F8 = -0x1F8
.text:0000850C var_18 = -0x18
.text:0000850C var_14 = -0x14
.text:0000850C
.text:0000850C 02 00 A0 E3 MOV R0, #2 ; domain
.text:00008510 70 40 2D E9 STMFD SP!, {R4-R6,LR}
.text:00008514 00 10 A0 E1 MOV R1, R0 ; type
.text:00008518 82 DF 4D E2 SUB SP, SP, #0x208
.text:0000851C 00 20 A0 E3 MOV R2, #0 ; protocol
.text:00008520 C5 FF FF EB BL socket
.text:00008524 00 00 50 E3 CMP R0, #0
.text:00008528 2B 00 00 BA BLT loc_85DC
.text:0000852C 02 3C A0 E3 MOV R3, #0x200 ; 512
.text:00008530 B4 10 9F E5 LDR R1, =0x8912 ; request
.text:00008534 02 2C 8D E2 ADD R2, SP, #0x218+var_18 ; R2 = SP + 512
.text:00008538 00 32 8D E5 STR R3, [SP,#0x218+var_18] ; [SP + 512] = 512;
.text:00008538 ; ifconf.ifc_len = 512;
.text:00008538 ; =====================
.text:0000853C 04 D2 8D E5 STR SP, [SP,#0x218+var_14] ; [SP + 512 + 4] = SP,
.text:0000853C ; 可以看出SP开始的512Bytes空间即char buf[512],
.text:0000853C ; ifconf.ifc_buf = buf;
.text:0000853C ; =====================
.text:00008540 C0 FF FF EB BL ioctl ; R0为socket()函数的返回值,未曾改变,作为第一个参数
.text:00008540 ; R1是SIOCGIFCONF的数值
.text:00008540 ; R2为SP+512,也就是ifconf结构体的地址。
.text:00008540 ; =========================================
.text:00008544 00 62 9D E5 LDR R6, [SP,#0x218+var_18] ; 获取ifconf.ifc_len,即ioctl返回的长度
.text:00008548 0D 40 A0 E1 MOV R4, SP
.text:0000854C A6 62 B0 E1 MOVS R6, R6,LSR#5
.text:00008550 1E 00 00 0A BEQ loc_85D0 ; 这个东西就是,i = ifconf_len/sizeof(struct ifreq)的一部分,
.text:00008550 ; ifreq是32字节,逻辑右移5位若为0,则i=0,即不存在该IP地址。
.text:00008550 ; 此时函数返回0。
.text:00008550 ; ================================================
.text:00008554 14 00 9D E5 LDR R0, [SP,#0x218+in] ; in = -0x204 偏移0x14,
;inet_ntoa(((struct sockaddr_in*)&(ifr->ifr_addr))->sin_addr)
; 也就是说sin_addr在ifreq中的偏移是0x14
.text:00008558 AE FF FF EB BL inet_ntoa ; sin_addr在sockaddr_in结构体中的偏移。
.text:00008558 ; 即将sin_addr的值传递给inet_ntoa()函数。
.text:00008558 ; ======================================
.text:0000855C 01 60 46 E2 SUB R6, R6, #1
.text:00008560 20 40 8D E2 ADD R4, SP, #0x218+var_1F8 ;地址增加32,移至下一个ifreq结构首地址
.text:00008564 00 10 A0 E1 MOV R1, R0
.text:00008568 80 00 9F E5 LDR R0, =aLocalAddrSN ; "local addr = [%s]/n"
.text:0000856C B8 FF FF EB BL printf
.text:00008570 00 50 56 E2 SUBS R5, R6, #0
.text:00008574 01 60 06 E2 AND R6, R6, #1
.text:00008578 14 00 00 0A BEQ loc_85D0
.text:0000857C 00 00 56 E3 CMP R6, #0
.text:00008580 03 00 00 0A BEQ loc_8594
.text:00008584 14 00 94 E5 LDR R0, [R4,#0x14] ; in ;sin_addr距该结构体首地址的偏移为0x14
.text:00008588 A2 FF FF EB BL inet_ntoa
.text:0000858C 00 10 A0 E1 MOV R1, R0
.text:00008590 09 00 00 EA B loc_85BC
.text:00008594 ; ---------------------------------------------------------------------------
.text:00008594
.text:00008594 loc_8594 ; CODE XREF: isIfceExist(char const*)+74j
.text:00008594 ; isIfceExist(char const*)+C0j
.text:00008594 14 00 94 E5 LDR R0, [R4,#0x14] ; in
.text:00008598 9E FF FF EB BL inet_ntoa
.text:0000859C 20 40 84 E2 ADD R4, R4, #0x20
.text:000085A0 01 50 45 E2 SUB R5, R5, #1
.text:000085A4 00 10 A0 E1 MOV R1, R0
.text:000085A8 40 00 9F E5 LDR R0, =aLocalAddrSN ; "local addr = [%s]/n"
.text:000085AC A8 FF FF EB BL printf
.text:000085B0 14 00 94 E5 LDR R0, [R4,#0x14] ; in
.text:000085B4 97 FF FF EB BL inet_ntoa
.text:000085B8 00 10 A0 E1 MOV R1, R0
.text:000085BC
.text:000085BC loc_85BC ; CODE XREF: isIfceExist(char const*)+84j
.text:000085BC 2C 00 9F E5 LDR R0, =aLocalAddrSN ; "local addr = [%s]/n"
.text:000085C0 A3 FF FF EB BL printf
.text:000085C4 01 50 55 E2 SUBS R5, R5, #1
.text:000085C8 20 40 84 E2 ADD R4, R4, #0x20
.text:000085CC F0 FF FF 1A BNE loc_8594
.text:000085D0
.text:000085D0 loc_85D0 ; CODE XREF: isIfceExist(char const*)+44j
.text:000085D0 ; isIfceExist(char const*)+6Cj
.text:000085D0 00 00 A0 E3 MOV R0, #0
.text:000085D4
.text:000085D4 loc_85D4 ; CODE XREF: isIfceExist(char const*)+DCj
.text:000085D4 82 DF 8D E2 ADD SP, SP, #0x208
.text:000085D8 70 80 BD E8 LDMFD SP!, {R4-R6,PC} ;函数返回,返回值0
.text:000085DC ; ---------------------------------------------------------------------------
.text:000085DC
.text:000085DC loc_85DC ; CODE XREF: isIfceExist(char const*)+1Cj
.text:000085DC 10 00 9F E5 LDR R0, =aSocket ; "socket"
.text:000085E0 92 FF FF EB BL perror
.text:000085E4 00 00 E0 E3 MOV R0, #0xFFFFFFFF
.text:000085E8 F9 FF FF EA B loc_85D4 ;错误返回,错误码-1
.text:000085E8 ; End of function isIfceExist(char const*)
.text:000085E8
.text:000085E8 ; ---------------------------------------------------------------------------
.text:000085EC ; unsigned __int32 request
.text:000085EC 12 89 00 00 request DCD 0x8912 ; DATA XREF: isIfceExist(char const*)+24r
.text:000085F0 ; char *format
.text:000085F0 E8 86 00 00 format DCD aLocalAddrSN ; DATA XREF: isIfceExist(char const*)+5Cr
.text:000085F0 ; isIfceExist(char const*)+9Cr ...
.text:000085F0 ; "local addr = [%s]/n"
.text:000085F4 ; char *s
.text:000085F4 E0 86 00 00 s DCD aSocket ; DATA XREF: isIfceExist(char const*):loc_85DCr
.text:000085F4 ; "socket"
.text:00008674 main ; DATA XREF: .text:00008480o
.text:00008674 ; .text:off_8494o
.text:00008674 00 00 9F E5 LDR R0, =aWoca ; "woca"
.text:00008678 A3 FF FF EA B _ZL11isIfceExistPKc ; isIfceExist(char const*)
.text:00008678 ; End of function main
.text:00008678
.text:00008678 ; ---------------------------------------------------------------------------
.text:0000867C 78 87 00 00 off_867C DCD aWoca ; DATA XREF: mainr
.text:0000867C ; "woca"
isIfceExist(const char *ifceName)源码:
static int isIfceExist(const char *ifceName){
int sock_fd = -1;
if((sock_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("socket");
return FAIL;
}
struct ifconf ifconf;
char buf[512];
ifconf.ifc_len = 512;
ifconf.ifc_buf = buf;
ioctl(sock_fd, SIOCGIFCONF, &ifconf);
struct ifreq *ifr;
ifr = (struct ifreq*)buf;
int i = 0;
for(i = (ifconf.ifc_len / sizeof(struct ifreq)); i > 0; i--){
printf("local addr = [%s]\n",inet_ntoa(((struct sockaddr_in*)&(ifr->ifr_addr))->sin_addr));
ifr++;
}
return OK;
}
.text:0000850C ; isIfceExist(char const*)
.text:0000850C _ZL11isIfceExistPKc ; CODE XREF: main+4j
.text:0000850C
.text:0000850C in = -0x204
.text:0000850C var_1F8 = -0x1F8
.text:0000850C var_18 = -0x18
.text:0000850C var_14 = -0x14
.text:0000850C
.text:0000850C 02 00 A0 E3 MOV R0, #2 ; domain
.text:00008510 70 40 2D E9 STMFD SP!, {R4-R6,LR}
.text:00008514 00 10 A0 E1 MOV R1, R0 ; type
.text:00008518 82 DF 4D E2 SUB SP, SP, #0x208
.text:0000851C 00 20 A0 E3 MOV R2, #0 ; protocol
.text:00008520 C5 FF FF EB BL socket
.text:00008524 00 00 50 E3 CMP R0, #0
.text:00008528 2B 00 00 BA BLT loc_85DC
.text:0000852C 02 3C A0 E3 MOV R3, #0x200 ; 512
.text:00008530 B4 10 9F E5 LDR R1, =0x8912 ; request
.text:00008534 02 2C 8D E2 ADD R2, SP, #0x218+var_18 ; R2 = SP + 512
.text:00008538 00 32 8D E5 STR R3, [SP,#0x218+var_18] ; [SP + 512] = 512;
.text:00008538 ; ifconf.ifc_len = 512;
.text:00008538 ; =====================
.text:0000853C 04 D2 8D E5 STR SP, [SP,#0x218+var_14] ; [SP + 512 + 4] = SP,
.text:0000853C ; 可以看出SP开始的512Bytes空间即char buf[512],
.text:0000853C ; ifconf.ifc_buf = buf;
.text:0000853C ; =====================
.text:00008540 C0 FF FF EB BL ioctl ; R0为socket()函数的返回值,未曾改变,作为第一个参数
.text:00008540 ; R1是SIOCGIFCONF的数值
.text:00008540 ; R2为SP+512,也就是ifconf结构体的地址。
.text:00008540 ; =========================================
.text:00008544 00 62 9D E5 LDR R6, [SP,#0x218+var_18] ; 获取ifconf.ifc_len,即ioctl返回的长度
.text:00008548 0D 40 A0 E1 MOV R4, SP
.text:0000854C A6 62 B0 E1 MOVS R6, R6,LSR#5
.text:00008550 1E 00 00 0A BEQ loc_85D0 ; 这个东西就是,i = ifconf_len/sizeof(struct ifreq)的一部分,
.text:00008550 ; ifreq是32字节,逻辑右移5位若为0,则i=0,即不存在该IP地址。
.text:00008550 ; 此时函数返回0。
.text:00008550 ; ================================================
.text:00008554 14 00 9D E5 LDR R0, [SP,#0x218+in] ; in = -0x204 偏移0x14,
;inet_ntoa(((struct sockaddr_in*)&(ifr->ifr_addr))->sin_addr)
; 也就是说sin_addr在ifreq中的偏移是0x14
.text:00008558 AE FF FF EB BL inet_ntoa ; sin_addr在sockaddr_in结构体中的偏移。
.text:00008558 ; 即将sin_addr的值传递给inet_ntoa()函数。
.text:00008558 ; ======================================
.text:0000855C 01 60 46 E2 SUB R6, R6, #1
.text:00008560 20 40 8D E2 ADD R4, SP, #0x218+var_1F8 ;地址增加32,移至下一个ifreq结构首地址
.text:00008564 00 10 A0 E1 MOV R1, R0
.text:00008568 80 00 9F E5 LDR R0, =aLocalAddrSN ; "local addr = [%s]/n"
.text:0000856C B8 FF FF EB BL printf
.text:00008570 00 50 56 E2 SUBS R5, R6, #0
.text:00008574 01 60 06 E2 AND R6, R6, #1
.text:00008578 14 00 00 0A BEQ loc_85D0
.text:0000857C 00 00 56 E3 CMP R6, #0
.text:00008580 03 00 00 0A BEQ loc_8594
.text:00008584 14 00 94 E5 LDR R0, [R4,#0x14] ; in ;sin_addr距该结构体首地址的偏移为0x14
.text:00008588 A2 FF FF EB BL inet_ntoa
.text:0000858C 00 10 A0 E1 MOV R1, R0
.text:00008590 09 00 00 EA B loc_85BC
.text:00008594 ; ---------------------------------------------------------------------------
.text:00008594
.text:00008594 loc_8594 ; CODE XREF: isIfceExist(char const*)+74j
.text:00008594 ; isIfceExist(char const*)+C0j
.text:00008594 14 00 94 E5 LDR R0, [R4,#0x14] ; in
.text:00008598 9E FF FF EB BL inet_ntoa
.text:0000859C 20 40 84 E2 ADD R4, R4, #0x20
.text:000085A0 01 50 45 E2 SUB R5, R5, #1
.text:000085A4 00 10 A0 E1 MOV R1, R0
.text:000085A8 40 00 9F E5 LDR R0, =aLocalAddrSN ; "local addr = [%s]/n"
.text:000085AC A8 FF FF EB BL printf
.text:000085B0 14 00 94 E5 LDR R0, [R4,#0x14] ; in
.text:000085B4 97 FF FF EB BL inet_ntoa
.text:000085B8 00 10 A0 E1 MOV R1, R0
.text:000085BC
.text:000085BC loc_85BC ; CODE XREF: isIfceExist(char const*)+84j
.text:000085BC 2C 00 9F E5 LDR R0, =aLocalAddrSN ; "local addr = [%s]/n"
.text:000085C0 A3 FF FF EB BL printf
.text:000085C4 01 50 55 E2 SUBS R5, R5, #1
.text:000085C8 20 40 84 E2 ADD R4, R4, #0x20
.text:000085CC F0 FF FF 1A BNE loc_8594
.text:000085D0
.text:000085D0 loc_85D0 ; CODE XREF: isIfceExist(char const*)+44j
.text:000085D0 ; isIfceExist(char const*)+6Cj
.text:000085D0 00 00 A0 E3 MOV R0, #0
.text:000085D4
.text:000085D4 loc_85D4 ; CODE XREF: isIfceExist(char const*)+DCj
.text:000085D4 82 DF 8D E2 ADD SP, SP, #0x208
.text:000085D8 70 80 BD E8 LDMFD SP!, {R4-R6,PC} ;函数返回,返回值0
.text:000085DC ; ---------------------------------------------------------------------------
.text:000085DC
.text:000085DC loc_85DC ; CODE XREF: isIfceExist(char const*)+1Cj
.text:000085DC 10 00 9F E5 LDR R0, =aSocket ; "socket"
.text:000085E0 92 FF FF EB BL perror
.text:000085E4 00 00 E0 E3 MOV R0, #0xFFFFFFFF
.text:000085E8 F9 FF FF EA B loc_85D4 ;错误返回,错误码-1
.text:000085E8 ; End of function isIfceExist(char const*)
.text:000085E8
.text:000085E8 ; ---------------------------------------------------------------------------
.text:000085EC ; unsigned __int32 request
.text:000085EC 12 89 00 00 request DCD 0x8912 ; DATA XREF: isIfceExist(char const*)+24r
.text:000085F0 ; char *format
.text:000085F0 E8 86 00 00 format DCD aLocalAddrSN ; DATA XREF: isIfceExist(char const*)+5Cr
.text:000085F0 ; isIfceExist(char const*)+9Cr ...
.text:000085F0 ; "local addr = [%s]/n"
.text:000085F4 ; char *s
.text:000085F4 E0 86 00 00 s DCD aSocket ; DATA XREF: isIfceExist(char const*):loc_85DCr
.text:000085F4 ; "socket"