汇编中call printf参数压栈时错误理解
EAX, ECX,EDX,EBX均可以32bit,16bit,8bit访问,如下所示:
<-------------------EAX------------------------>
|<----------------------|-----------|----------->|
|<---------AX--------->|
|<---AH--->|<---AL--->|
测试代码如下:
.section .data
output:
.asciz "Value is:%x\n"
val:
.int .section .text
.globl main
main:
nop
movl $0x12345678, %eax
movl $, %ecx
movw %ax, %cx
pushw %cx
pushl $output
call printf
addl $, %esp movl $, %eax
movl $, %ebx
int $0x80
我的电脑是小端格式(MSB存于高位),所以预期的输出结果是:0x5678,但是我编译执行后结果是:0x2dec5678,前面多出了2个字节,但是明明我压栈的时候使用的pushw,原来是printf获取参数时使用的是4字节长度,所以虽然我压入的只有2个字节,但是它访问时以4字节访问。
将代码修改:
.section .data
output:
.asciz "Value is:%x\n"
val:
.int .section .text
.globl main
main:
nop
movl $0x12345678, %eax
movl %eax, %ecx
pushl %ecx
pushl $output
call printf
addl $, %esp movl $, %ecx
movw %ax, %cx
pushl %ecx
pushl $output
call printf
addl $, %esp movl $, %eax
movl $, %ebx
int $0x80
预期输出:
Value is:12345678
Value is:5678
结果输出:
Value is:12345678
Value is:12
起先还以为是将0x12345678的最高字节0x12传送到cx里面了,觉得相当怪异,明明使用的是movw,要错也是0x1234,分析了下,原来又是printf作怪,函数调用后,其返回值一般是存储在eax里面来传递的,而第一个printf的输出:Value is:12345678恰好有0x12,18个字符(含'\n'),所以代码执行完15行的call后,eax的值已被printf的返回值修改,而不是我预期的0x12345678。所以汇编里面调用库函数时,要特别注意某些特殊寄存器的特殊用途,特别是这些库是由其他高级语言通过编译工具生成的时候。
汇编中call printf参数压栈时错误理解的更多相关文章
- C语言函数参数压栈顺序为何是从右到左?(从左向右的话,碰到printf的会陷入死循环)
上学期学习了汇编语言,并在操作系统实验中使用了汇编+C语言混合编程,中间也了解了一些C语言与汇编语言的对应关系. 由于汇编语言是底层的编程语言,各种函数参数都要直接控制栈进行存取,在混合编程中,要用汇 ...
- c/c++的函数参数压栈顺序
整理日:2015年3月18日 为了这句话丢了很多次人.无所谓了,反正咱脸皮厚. 总结一下 编译出来的c/c++程序的参数压栈顺序只和编译器相关! 下面列举了一些常见的编译器的调用约定 VC6 调用约定 ...
- printf函数压栈解惑
最近看到一些程序员的笔试题目,经常会考到printf函数的参数压栈问题,总体来讲就是参数从右向左依次压栈,再出栈,但是今天看到一个看似很简单的题目,却一直找不到头绪.题目如下: #include &l ...
- printf函数压栈(i++/i--,++i/--i) 终极解密
#include <stdio.h> void main() { ; printf("%d %d %d %d\n", i, --i, i, i--); } 输出是“3 ...
- printf()函数压栈a++与++a的输出
printf()中a++与++a的输出问题 在C语言中有个很常用的函数printf(),使用时从右向左压栈,也就是说在printf("%d %d %d %d\n",a,a++,++ ...
- iOS中的堆(heap)和栈(stack)的理解
操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segme ...
- Fedora 20中解决zip解压文件时中文文件名的乱码问题[已解决]
该方法的原文地址: http://wangqige.com/the-solution-of-unzip-files-which-zip-under-windows/(链接已失效) 解决方法:保存如下P ...
- x86汇编寄存器,函数参数入栈说明
https://en.wikipedia.org/wiki/X86_calling_conventions
- arm汇编进入C函数分析,C函数压栈,出栈,传参,返回值
环境及代码介绍 环境和源码 由于有时候要透彻的理解C里面的一些细节问题,所有有必要看看汇编,首先这一切的开始就是从汇编代码进入C的main函数过程.这里不使用编译器自动生成的这部分汇编代码,因为编译器 ...
随机推荐
- jquery实现全选功能
主要是模拟一些网页中的表格实现全选功能. <form> 你爱好的运动是: <input type="checkbox" id="Check" ...
- angularjs post
/** * POST 1 * $http.post('http://localhost:8001/quickstart/task/create', { newTask: newTask }) */ / ...
- Gulp-前端进阶A-2
1.js压缩 注意在根目录的package.json文件里在成功安装uglify后要有 "gulp-uglify": "^1.5.4" 才行 var gulp ...
- JS中标准对象
JS中标准对象1:不要使用new Number().new Boolean().new String()创建包装对象:2:用parseInt()或parseFloat()来转换任意类型到number: ...
- JavaScript正则表达式小记
RegExp.html div.oembedall-githubrepos{border:1px solid #DDD;border-radius:4px;list-style-type:none;m ...
- RHEL7文件权限
本文介绍Linux下的文件权限 操作系统为RHEL7.2_X86_64 可以从以下三种访问方式限制访问权限: 1 只允许用户自己访问 2 允许一个预先指定的用户组中的用户访问 3 允许系统中的任何用户 ...
- ABAP程序系统字段中英文详解
SY-SUBRC: 系统执行某指令后,表示执行成功与否的变量,’0’ 表示成功SY-DBLNT: 被处理过的记录的笔数 SY-UNAME: 当前使用者登入SAP的USERNAME;SY-DATUM: ...
- iOS 删除 Main.storyboard 和 LaunchScreen.storyboard
第一步: 右键选中Main.storyboard —- delete —— Move to Trash LaunchScreen同理 第二步 点击工程名,就是最顶级目录 右侧出现general选项卡 ...
- Android网络编程基础
Android网络编程只TCP通信 TCP 服务器端工作的主要步骤如下.步骤1 调用ServerSocket(int port)创建一个ServerSocket,并绑定到指定端口上.步骤2 调用acc ...
- Runtime(动态添加属性)
下面通过一个实例展示一下Runtime(动态添加属性)的用法 下面对运行时添加属性用到的策略参数进行补充: 这样看来,前面的NSString* name用的策略是retain nonatomic就知道 ...