杨宇
很棒的分析过程!看得出功力深厚
2022-04-27
2
liu_liu
a - 2 字节
b - 1
c - 1
padding - 4
d - 8
union - 8
共 24 字节。
-------
但老师,我有些地方不太明白。
当给思考题中的结构体赋值(我给它起名叫 User),并且 union 赋值为浮点数 1.25,如下:
int main() {
struct User u = {1, 'a', 'b', 0x10000, .e = 1.25};
return 0;
}
汇编代码如下:
------
main:
push rbp
mov rbp, rsp
mov WORD PTR [rbp-32], 1
mov BYTE PTR [rbp-30], 97
mov BYTE PTR [rbp-29], 98
mov QWORD PTR [rbp-24], 65536
movsd xmm0, QWORD PTR .LC0[rip]
movsd QWORD PTR [rbp-16], xmm0
mov eax, 0
pop rbp
ret
.LC0:
.long 0
.long 1072955392
--------
.LC0 这段应该是浮点数 1.25 的值。
movsd xmm0, QWORD PTR .LC0[rip],我猜它的含义是把 1.25 的值放入 xmm0 寄存器中。
1. 那 .LC0[rip] 的意思是什么呢?为什么要把 rip 传入呢?
2. 为什么 .LCO 中使用两个 .long 来表示呢?这里的具体含义是什么呢?
望老师解答~
作者回复:很好的问题!下面是回答:
1. 这里的 “.LC0[rip]” 实际上是汇编代码中的一种通过 rip 寄存器来进行相对寻址的方式,一般也称为 pc-relative 或 rip-relative。rip 寄存器中存放着下一条将要执行的指令。而这里该条指令的寻址结果便是 .LC0 这个 label 的开头。
2. .long 是一个汇编指示标记,用于让汇编器在当前这个位置保留一个 4 字节的值。这里第一个 .long 0 是 1.25 对应二进制表示的低 32 位;第二个 .long 1072955392 则是对应高 32 位的十进制值。
2021-12-22
3
Fan
不错,就喜欢这种讲细节的课程。
2021-12-29
5
疯码
总算明白对齐规则怎么来的了,感谢
2022-01-05
1
赵岩松
连续看到现在,受益良多,非常感谢!
作者回复:很高兴对你有帮助 : )
2021-12-19
2
友
置顶
push 指令等价 先 sub 然后 mov rbp,(rsp) 括号就是 将rbp保存到rsp sub之后的地址去 这里我就感觉 每次push之后 把上一个函数的 rbp保存了起来 这里的rbp应该存的是当前函数帧首地址 应该就是保证回到了当前函数并且里面的数据也还保存在。 至于 mov rbp rsp 应该就是将当前帧首保存到了 rbp里面 然后之前的rbp已经push到了rsp中 感觉说的有点思路不清晰了 害还是没有理解的很好
哦对了 关于 leave 如果按照上面所述
我只需要将这个 mov rbp rsp 就破坏了当前函数的栈结构 然后 pop 就回到了上一个函数的栈结构的首地址 此时 rsp应该是指向的返回地址
call 指令我想应该是 push rsp ,返回地址
ret 是 jmp (rsp)
老师上面是我的一些小理解。我感觉肯定有地方有错误希望老师指导一下我🌝🌝
作者回复:大部分理解都是对的哈。不过关于 rbp 里面保存的内容,只要知道它是上一个栈帧需要使用的、用来计算栈高度的信息就好。而 rsp 指向的是栈内存的顶部,也不用把它跟栈帧混在一起理解哈。因为其实所谓的“帧首”很难去界定,理论上按照小端序理解,可以认为“当前函数返回地址+8”(64位)的位置是上一个栈帧的开头。但一般很少这么讲。
2021-12-18
友
老师您这张寄存器的图让我想起来当时看csapp第三章的感觉 我一定要跟着你把c学好
作者回复:嗯嗯,加油!
2021-12-16
1
pedro
竟然有一种像当年读CSAPP第三章的感觉!
空语句用的少,多数时候用来做空循环体吧。
作者回复:没错!这是一种常见的场景。举个例子:
#include <stdio.h>
int main() {
char c;
while ((c = getchar()) == ' ');
printf("%c", c);
}
2021-12-13
6
Y
使用C语言很多年, 一直向深入理解C和编译和运行底层原理,这个课程早上点就更好了
2021-12-08
7
pedro
讲的好,拍案叫绝!
2021-12-08
3
编辑推荐
讲师的其他课程
看过的人还看了