https://gcc.godbolt.org/ 编译选项 输入 -O0 或 -O1
注: x64约定传参 .
windows rcx rdx r8 r9 esp+20h esp+28h esp+30h ....
linux rdi, rsi, rdx, rcx, r8, r9 esp+20h
image.png
gcc 9.4
#include <stdio.h>
// linux rdi, rsi, rdx, rcx, r8, r9 esp+20h
void myputc(char* cptr) {
}
int main(void) {
char*********** a;
// a=0x7ffc617b0ac8;
char* cs[18] = {'a',&a, 'b', 'c', 'd', 'e', 'f', 'g', 'h',
'z', 'j', 'k', 'm', 'n', 'p', 'w'};
a = &cs;
printf("%p\n", &a);
printf("%c\n", *(a));
// printf("%c\n", *(*a)); //run 的时候报错
// printf("%c\n", **a); //与上面有括号的一样run 的时候报错
printf("%c\n", *(a + 1));
printf("%p\n", *(a + 1));
printf("%p\n", *(a + 2));
printf("%c\n", *a + 1);
printf("%c\n", *a + 2);
for(int i=0;i<18;i++){
printf("ci: %p\n", *(a + i));
}
return 0;
}
//gcc9.4 -O1
myputc:
ret
.LC0:
.string "%p\n"
.LC1:
.string "%c\n"
main:
subq $40, %rsp
char cs[18] ;数组在汇编中没了 rsp是开头地址。 也是cs变量的地址。
movabsq $7523094288207667809, %rax
movabsq $33619141813037690, %rdx
movq %rax, (%rsp)
movq %rdx, 8(%rsp)
movw $0, 16(%rsp)
a=&cs; 24(rsp) 是变量a的地址,现在存的内容是rsp
movq %rsp, 24(%rsp)
#printf("%p\n", &a);
leaq 24(%rsp), %rsi
movl $.LC0, %edi
call printf
printf("%c\n", *(a)) ;输出是 'a'
movq 24(%rsp), %rax
movq (%rax), %rsi
movl $.LC1, %edi
call printf
printf("%c\n", *(*a)); //run 的时候报错
movq 24(%rsp), %rax
movq (%rax), %rax ;此处rax是a 97
movq (%rax), %rsi ;这里取地址 97 的时候报错
movl $.LC1, %edi
call printf
printf("%c\n", *(a + 1)); ; 'z'
movq 24(%rsp), %rax
movq 8(%rax), %rsi ;+8 就是z的地址 因为a 现在是多级指针 就是指针类型了 所以x64要加8
movl $.LC1, %edi
call printf
printf("%c\n", *a + 1);
movq 24(%rsp), %rax
movq (%rax), %rsi
addq $8, %rsi ;直接+8 'a' 97+8 105='i' 应该是有点bug
movl $.LC1, %edi
call printf
printf("%c\n", *a + 2);
movq 24(%rsp), %rax
movq (%rax), %rsi
addq $16, %rsi ;97+16 =113 'q'
movl $.LC1, %edi
call printf
addq $40, %rsp
ret
#include<stdio.h>
void s(int** zp,int***** zp3,char** char1){
int**** p=12;
p=33;
*p=0;
**p=1;
***p=2;
****p=4;
// *****p=99; 大于4个就错了
*zp=10;
**zp=11;
int one =88;
one=998;
zp3=&one;
****zp3=&one;
*****zp3=one;
char1=*zp3;
p=*char1;
p=char1;
p=&char1;
p=&*char1;
p=&**char1;
}
linux at&t汇编 .似乎要清晰点. mov 指令后面跟q movq 的意思是8字节. movb 一个byte ..
s:
pushq %rbp
movq %rsp, %rbp
movq %rdi, -24(%rbp)
movq %rsi, -32(%rbp)
movq %rdx, -40(%rbp)
movq $12, -8(%rbp)
movq $33, -8(%rbp)
movq -8(%rbp), %rax
movq $0, (%rax)
movq -8(%rbp), %rax
movq (%rax), %rax
movq $1, (%rax)
movq -8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq $2, (%rax)
movq -8(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq (%rax), %rax
movl $4, (%rax)
movq -24(%rbp), %rax
movq $10, (%rax)
movq -24(%rbp), %rax
movq (%rax), %rax
movl $11, (%rax)
movl $88, -12(%rbp)
movl $998, -12(%rbp)
leaq -12(%rbp), %rax
movq %rax, -32(%rbp)
movq -32(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq (%rax), %rax
leaq -12(%rbp), %rdx
movq %rdx, (%rax)
movq -32(%rbp), %rax
movq (%rax), %rax
movq (%rax), %rax
movq (%rax), %rax
movq (%rax), %rax
movl -12(%rbp), %edx
movl %edx, (%rax)
movq -32(%rbp), %rax
movq (%rax), %rax
movq %rax, -40(%rbp)
movq -40(%rbp), %rax
movq (%rax), %rax
movq %rax, -8(%rbp)
movq -40(%rbp), %rdx
movq -8(%rbp), %rax
movq %rdx, (%rax)
movq -40(%rbp), %rax
movq %rax, -8(%rbp)
leaq -40(%rbp), %rax
movq %rax, -8(%rbp)
movq -40(%rbp), %rax
movq %rax, -8(%rbp)
p=&**char1;
movq -40(%rbp), %rax ; 把 char1 一个地址变量(二级指针) rpb-40是char1作为局部变量的地址,此时取得是
char1内容.
movq (%rax), %rax 然后把char1作为地址 获取该地址8个字节内容 由movq 和 rax rpb决定字节数.
movq %rax, -8(%rbp) 获取的内容8个字节值放到 rbp-8. 语义为 p局部变量中. 底层中没有变量名了.只有
确定的地址 "当做" 例如p已转化为了 rbp-8
nop
popq %rbp
ret
windows 汇编
s:
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-24], rdi
mov QWORD PTR [rbp-32], rsi
mov QWORD PTR [rbp-40], rdx
mov QWORD PTR [rbp-8], 12
mov QWORD PTR [rbp-8], 33
*p=0; 等于 mov [[rbp-8]] 0
mov rax, QWORD PTR [rbp-8]
mov QWORD PTR [rax], 0
**p=1;
mov rax, QWORD PTR [rbp-8]
mov rax, QWORD PTR [rax]
mov QWORD PTR [rax], 1
***p=2;
mov rax, QWORD PTR [rbp-8]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
mov QWORD PTR [rax], 2
****p=4;
mov rax, QWORD PTR [rbp-8]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
mov DWORD PTR [rax], 4
mov rax, QWORD PTR [rbp-24]
mov QWORD PTR [rax], 10
mov rax, QWORD PTR [rbp-24]
mov rax, QWORD PTR [rax]
mov DWORD PTR [rax], 11
mov DWORD PTR [rbp-12], 88 ;int one =88;
mov DWORD PTR [rbp-12], 998 ;one=998; 局部变量在栈上.
;zp3=&one;
lea rax, [rbp-12]
mov QWORD PTR [rbp-32], rax
;****zp3=&one;
mov rax, QWORD PTR [rbp-32]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
lea rdx, [rbp-12]
mov QWORD PTR [rax], rdx
; *****zp3=one;
mov rax, QWORD PTR [rbp-32]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
mov rax, QWORD PTR [rax]
mov edx, DWORD PTR [rbp-12]
mov DWORD PTR [rax], edx
char1=*zp3;
mov rax, QWORD PTR [rbp-32]
mov rax, QWORD PTR [rax]
mov QWORD PTR [rbp-40], rax
p=*char1;
mov rax, QWORD PTR [rbp-40]
mov rax, QWORD PTR [rax]
mov QWORD PTR [rbp-8], rax
*p=char1;
mov rax, QWORD PTR [rbp-8]
mov rdx, QWORD PTR [rbp-40]
mov QWORD PTR [rax], rdx
p=char1;
mov rax, QWORD PTR [rbp-40]
mov QWORD PTR [rbp-8], rax
p=&char1;
lea rax, [rbp-40]
mov QWORD PTR [rbp-8], rax
p=&*char1;
mov rax, QWORD PTR [rbp-40]
mov QWORD PTR [rbp-8], rax
p=&**char1;
mov rax, QWORD PTR [rbp-40]
mov rax, QWORD PTR [rax]
mov QWORD PTR [rbp-8], rax
nop
pop rbp
ret
#include<stdio.h>
// 二级指针传参 练习
int sq(char** num) {
*num="feng";
return strlen(num);
}
void feng(){
char* one="a";
int ai=sq(&one);
printf("c: %s \n",one,ai);
}
int sq1(char* num) {
printf("ca: %s \n",num);
num="feng";
return 2;
}
void feng1(){
char* one="a";
sq1(one);
printf("c: %s \n",one);
}
.LC0:
.string "feng"
sq:
sub rsp, 8
mov QWORD PTR [rdi], OFFSET FLAT:.LC0
call strlen
add rsp, 8
ret
.LC1:
.string "a"
.LC2:
.string "c: %s \n"
feng:
sub rsp, 24
mov QWORD PTR [rsp+8], OFFSET FLAT:.LC1
lea rdi, [rsp+8]
call sq
mov edx, eax
mov rsi, QWORD PTR [rsp+8]
mov edi, OFFSET FLAT:.LC2
mov eax, 0
call printf
add rsp, 24
ret
.LC3:
.string "ca: %s \n"
sq1:
sub rsp, 8
mov rsi, rdi
mov edi, OFFSET FLAT:.LC3
mov eax, 0
call printf
mov eax, 2
add rsp, 8
ret
feng1:
sub rsp, 8
mov edi, OFFSET FLAT:.LC1
call sq1
mov esi, OFFSET FLAT:.LC1
mov edi, OFFSET FLAT:.LC2
mov eax, 0
call printf
add rsp, 8
ret