汇编中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函数过程.这里不使用编译器自动生成的这部分汇编代码,因为编译器 ...
随机推荐
- oracle触发器类型
http://www.cnblogs.com/roucheng/p/3506033.html 触发器是许多关系数据库系统都提供的一项技术.在ORACLE系统里,触发器类似过程和函数,都有声明,执行和异 ...
- Studio for WPF:定制 C1WPFChart 标记
在本篇文章中,我们将阐述如何定制 C1WPFChart 数据点的标记. 下面分步讲解实现: 1.定制自定义样式: 1: <Window.Resources> 2: <Style x: ...
- PHP学习笔记:利用百度api实现手机归属地查询
从来没有用过api,都不知道怎么获得api的数据,跟着demo,然后修改,终于实现了手机号码查询的功能,代码和说明很全,大家试试. <?php /** * Created by jianqing ...
- python peewee.ImproperlyConfigured: MySQLdb or PyMySQL must be installed.
最近在学习Python,打算先看两个在线教程,再在github上找几个开源的项目练习一下,在学到“被解放的姜戈”时遇到django同步数据库时无法执行的错误,记录一下. 错误现象: 执行python ...
- 开源项目Foq简介
Foq是一个轻量级-线程安全的mocking类库.使用它来mock抽象类与接口这是我们通常的做法.Foq的名字来自Moq,如果你使用过Moq的话,自然后联想到它能做什么.Foq主要是为了F#的 ...
- Angular 核心概念
module(模块) 作用 通过模块对页面进行业务上的划分,根据不同的功能划分不同的模块. 将重复使用的指令或者过滤器之类的代码做成模块,方便复用 注意必须指定第二个参数,否则变成找到已经定义的模块 ...
- 初次接触mootools
以下是今天所学代码,网上有这篇博客可供参考,另外还是推荐官方文档 ,以下是今天所敲代码: //用mootools创建类的方式: //方式1:用标准方式传入一个对象字面量 /* var Person = ...
- python基础(2)
1.lambda函数 学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,函数同样有简单的表示方法 # ###################### 普通函数 ######### ...
- 关于oracle-12514错误的修改方法
原因1: 打开文件"<OracleHome>/network/admin/listener.ora",添加 (SID_DESC = (GLOBAL_DB ...
- 2015年第14本(英文第10本):The A.B.C. Murders (A.B.C谋杀案)
书名:The ABC Murders 推荐指数:5星 作者:Agatha Christie 单词数:7万 不重复单词数:不详 首万词不重复单词数:不详 蓝思值:740 阅读时间:2015年7月18日 ...