您现在的位置是:主页 > news > 江西求做网站/广告公司推广软文

江西求做网站/广告公司推广软文

admin2025/5/23 14:27:45news

简介江西求做网站,广告公司推广软文,网络最好的运营商,莒县城阳网站建设2019独角兽企业重金招聘Python工程师标准>>> 今天在学习 C 语言内嵌汇编的实验过程中,发现内嵌汇编极容易造成段错误。经过分析,我发现错误源于对于栈指针 esp 的不当操作导致的,现将整个问题记录如下。 实验需求是,在…

江西求做网站,广告公司推广软文,网络最好的运营商,莒县城阳网站建设2019独角兽企业重金招聘Python工程师标准>>> 今天在学习 C 语言内嵌汇编的实验过程中,发现内嵌汇编极容易造成段错误。经过分析,我发现错误源于对于栈指针 esp 的不当操作导致的,现将整个问题记录如下。 实验需求是,在…

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

今天在学习 C 语言内嵌汇编的实验过程中,发现内嵌汇编极容易造成段错误。经过分析,我发现错误源于对于栈指针 esp 的不当操作导致的,现将整个问题记录如下。

实验需求是,在内存中分配一段空间用作函数调用栈。代码如下:

/* test.c */#include <stdio.h>#define STACK_SIZE 1024		// 1Kint main(void)
{unsigned char stack[STACK_SIZE];int i;// A. Initialize stackasm volatile ("pushl %%ebp\n\t"		// store ebp"movl %%esp, %%ebp\n\t"		// temp esp"movl %0, %%esp\n\t"		// new esp"pushl %%ebp\n\t"		// store old esp"movl %%esp, %%ebp\n\t"		// new ebp :: "m" (stack));// Any codes here// Check the status of the stackfor (i = 0; i < STACK_SIZE; i++){printf("%02X ", stack[i]);}printf("\n");// Restore system-allocated stackasm volatile ("movl %%ebp, %%esp\n\t"		// clear stack"popl %%ebp\n\t"		// obtain old esp"movl %%ebp, %%esp\n\t"		// restore esp"popl %%ebp\n\t"		// restore ebp::			);return 0;
}

这段代码可以通过编译,然而运行的时候总是出现 `Segmentation fault`。没办法,我只能首先用 `gcc -S test.c -o test.s -m32` 查看生成的汇编代码。这里给出中间部分输出栈内容部分的汇编代码:

#NO_APPmovl	$0, 24(%esp)jmp	.L2
.L3:leal	28(%esp), %edxmovl	24(%esp), %eaxaddl	%edx, %eaxmovzbl	(%eax), %eaxmovzbl	%al, %eaxmovl	%eax, 4(%esp)movl	$.LC0, (%esp)call	printfaddl	$1, 24(%esp)
.L2:cmpl	$1023, 24(%esp)jle	.L3movl	$10, (%esp)call	putchar



从这里可以看到,对于所有局部变量的寻址采用的都是通过相对于 esp 偏移的间接寻址方式,当在内嵌汇编中更改了 esp 后,寻址发生错误,所以肯定不能输出我们想要的结果了。那为什么会发生 `Segmentation fault` 呢?其原因在于,自己分配的栈空间实际上还是放置于栈中的,而在 A 处的汇编代码将 esp 指针往栈底方向进行了偏移,而 stack 相对于 esp 的偏移是一个固定值,导致了访问 stack 第一个元素的时候就已经来到了程序栈空间之外,从而触发了 `Segmentation fault`。

在更简单的情景中也可能因为 esp 和 ebp 的移动引起程序工作的异常。例如下面这段简单的代码:

/* test2.c */
#include <stdio.h>int main(void)
{int x = 2;asm volatile ("pushl %%esp\n\t":);printf("%X", x);return 0;
}



某一次运行的时候输出结果是这样的:  804845B

这个错误的来源也是因为压栈导致了 esp 指针的移动,从而在通过间接寻址时查找 x 的时候发生了异常。找到的不是 x ,而是我们刚刚压入的 esp 寄存器的部分字节。

因此,一个好习惯是:在 C 语言中内嵌汇编时,如果需要移动栈指针,必须在结束汇编代码前将栈指针恢复到内嵌汇编前的状态。

转载于:https://my.oschina.net/siyuany/blog/385299