howzyao 发表于 2022-9-16 14:17:54

欢迎想深入学习C的进来讨论图片

今天学了调试,如图,至少看到了esp:

网上的解释是:
esp(32位)/rsp(64位):
栈顶指针,指向栈的顶部

这里看到的是 a,b,c
它们之间,间隔的是距离是:0x14 0x18 0x 1c
从中可以看出,都是4的距离.
不知道是不是4字节的意思:
0000 0000 0x14
0000 0000
0000 0000
0000 0000

0000 0000 0x18
这么远的意思.
如果是,那么,就学到了 sizeof(a)==4 为真.

jackz007 发表于 2022-9-16 14:43:14

本帖最后由 jackz007 于 2022-9-16 14:49 编辑

      可以看得出来,你这个是 32 位的程序。

      对于函数的局部变量 a,b,c 而言,它们会在运行时从堆栈动态取得存储空间,也就是说,这些变量只有在函数被调用的时候才会临时产生,如果它们是 int 或 float 型变量,那么,每个变量均占用 4 个字节,变量 a、b、c 实际上就是这 3 个变量所占用内存空间的映射。

howzyao 发表于 2022-9-16 14:48:59

嗯,谢谢楼上确认。
0x401326开始,也是变化为以下
0x40132e
0x401336
也是4的距离:单位是字节吗?
1字节==8个位吗?
32位长度==4字节==一个int占用的内存长度

howzyao 发表于 2022-9-16 14:50:03

还都是用movl的方式变化的等距离

jackz007 发表于 2022-9-16 15:02:58

本帖最后由 jackz007 于 2022-9-16 15:26 编辑

howzyao 发表于 2022-9-16 14:48
嗯,谢谢楼上确认。
0x401326开始,也是变化为以下
0x40132e


0x40131e    sub   $0x20 , %esp                                                   <-- 在堆栈中预留出 0x20 个字节,供函数的各种局部变量使用
0x401321    call    0x41eb40 <__main>                                          <-- 你应该单步跟踪进入这个函数(0x41eb40 ),然后才能看到你写的代码
      

jackz007 发表于 2022-9-16 15:39:59

本帖最后由 jackz007 于 2022-9-16 15:44 编辑

howzyao 发表于 2022-9-16 14:50
还都是用movl的方式变化的等距离

         我也写了一个和你一模一样的代码,这是在我这边用调试器看到的代码样子
00401350/$55                         push    ebp
00401351|.89E5                     mov   ebp, esp
00401353|.83E4 F0                  and   esp, FFFFFFF0
00401356|.83EC 20                  sub   esp, 20                                           ; 在堆栈中开辟出 0x20 字节空间供局部变量使用
00401359|.E8 F2050000                call    00401950
0040135E|.C74424 1C 09000000         mov   dword ptr , 9                           ; <--- a = 9
00401366|.C74424 18 09000000         mov   dword ptr , 9                           ; <--- b = 9
0040136E|.C74424 14 00000000         mov   dword ptr , 0                           ; <--- c = 0
00401376|.8B5424 1C                  mov   edx, dword ptr                            ; <--- edx = a
0040137A|.8B4424 18                  mov   eax, dword ptr                            ; <--- eax = b
0040137E|.01D0                     add   eax, edx                                          ; eax = b + a
00401380|.894424 14                  mov   dword ptr , eax                           ; <--- c = eax
00401384|.C70424 24304000            mov   dword ptr , 00403024                         ; |ASCII "pause"
0040138B|.E8 30080000                call    <jmp.&msvcrt.system>                              ; \system
00401390|.B8 00000000                mov   eax, 0                                          ; eax = 0 就是 return 0 中的那个 0
00401395|.C9                         leave
00401396\.C3                         retn
00401397      90                         nop
      你的反汇编代码采用了 AT&T 风格,我这个采用的是 Intel 风格,二者虽然在指令文本形式上存在不同,但是,机器指令本身并无本质的差别。

jhanker 发表于 2022-9-16 16:30:13

用Vc6.0调试看看更直观!

howzyao 发表于 2022-9-16 18:52:26

sub $0x20 , %esp
预留,美元符 %esp栈顶指针的格式。
0x20 就是2000 0000 一个字节的边度十进制数,就是全部加起来1248 16 32 64 128
都是0,就是128*2=256字节==0x20
放入了这个栈内存,这个栈内存叫做esp,它是栈顶,也是个指针,指向顶部之下的255字节的全部空间。
是这样理解吗?
谢谢啊,谢谢,

jackz007 发表于 2022-9-16 19:28:46

本帖最后由 jackz007 于 2022-9-16 19:43 编辑

howzyao 发表于 2022-9-16 18:52
sub $0x20 , %esp
预留,美元符 %esp栈顶指针的格式。
0x20 就是2000 0000 一个字节的边度十进制数,就 ...

    你到底说了些什么乱七八糟的东西?
       sub$0x20 , %esp
    在 AT&T 汇编中,立即数前面要加 $ 符号,$0x20 就是 0x20,这一句的意思是将栈顶指针 %esp 的值减去 0x20,%esp 指针会因此而向下移动 0x20 字节,这样操作的结果,意味着这 0x20 个字节的堆栈空间已经被占用,那么,%esp ~%esp + 0x1f 一共 32(0x20) 个字节的内存就属于被保护空间,之后,所有的堆栈操作都不会占用到这个空间。

    预留的这 32 个字节的空间足够供 8 个整(或浮点)型变量进行使用(4 x 8 = 32)。

howzyao 发表于 2022-9-16 19:48:24

立即数前面要加 $ 符号 sub$0x20 , %esp
将栈顶指针 %esp 的值减去 0x20,%esp 指针会因此而向下移动 0x20 字节

我能不能向你从个师?你收不收弟子?

谢谢指导啊.

howzyao 发表于 2022-9-16 19:51:00

立即数
以前听到了,以为就是在main中 随手输的 右值,现在才进一步明白.上升到寄存器的微观上,立即数 实际上是 空间长短的数量.

jackz007 发表于 2022-9-16 20:01:33

本帖最后由 jackz007 于 2022-9-16 20:13 编辑

howzyao 发表于 2022-9-16 19:51
立即数
以前听到了,以为就是在main中 随手输的 右值,现在才进一步明白.上升到寄存器的微观上,立即数 实际 ...

       立即数就是一个 const,就是说,它是一个现成的数,没有那么多其他意思,编译器在编译代码的时候它就已经有了确切的数值,从而被编译器直接写入了汇编指令,就好像为a,b,c 赋初值的指令中所出现的 $0x9 , $0x9, $0x0,这三个数就属于立即数。

howzyao 发表于 2022-9-16 20:51:00

本帖最后由 howzyao 于 2022-9-16 21:04 编辑


自己的调式理解:

mov到cmpl之间,处于一段循环:


始 mov %esp,%eax

   cmpl %esp    终

esp eax
对于这两个概念,
查了一下:

AX:累积暂存器

EAX、ECX、EDX、EBX:為ax,bx,cx,dx的延伸,各為32位元

EAX 是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器。

ESP 专门用作堆栈指针,被形象地称为栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的

数据越多,ESP也就越来越小。在32位平台上,ESP每次减少4字节。

esp:寄存器存放当前线程的栈顶指针
ebp:寄存器存放当前线程的栈底指针

以上图的调试源码是这:
for(int i=0;i<le;i++)
      b=0.1+(double)i;
页: [1]
查看完整版本: 欢迎想深入学习C的进来讨论图片