如何获取开方内联汇编获取系统时间于iOS工作

ARM汇编(11)
汇编(12)
这篇介绍一下c内联汇编的使用,准确的说,内联汇编不算是汇编的语法,而是c/c++的语法,虽然c/c++是有标准参考的,但是不同编译器使用的 汇编不同,导致内联汇编是编译器相关的。这里介绍vc和gcc下c的内联汇编使用,vc使用masm语法,gcc自然是AT&T语法。
一般来讲,MASM的语法规则较多,也比较复杂,不过内联汇编却相当的方便,相反,AT&T的内联汇编语法规非常复杂,这里先介绍简单的MASM内联。
vc环境下内联汇编语法规则如下:
__asm statement
statement-1
statement-2
statement-n
这里的指令即MASM程序,但是有一些限制如下:
不能使用数据定义伪指令
不能定义结构等复杂数据类型
不能使用宏,或宏操作符
不能引用段名
当然这里只是简单的介绍一下,其中的细节只能在实践中体会了,接下来举一个简单的例子来说明内联汇编的使用:
/** 计算两个参数的积 */
int testAssembler(int p1, int p2)
mov eax, p1
int main()
testAssembler(3, 5);
__asm mov result,
printf(&result is %d\n&, result);
这里 testAssembler 函数中使用内联汇编计算了参数的积,调用点并未接受其返回值,因为函数返回值是由eax寄存器返回,则再次使用内联汇编可以取到返回值。
可以看到MASM内联汇编是十分简单的,接下来看gcc的内联语法:
: 输出部分
: 输入部分
: 破坏描述
先来说语句模板,这里的语句即为AT&T的基本语法,与MASM不同的是这里不能直接使用局部变量,倒是可以引用全局变量,指 令之间使用”;”, “\n”, “\n\t” 分割,后面的部分是可选的,如果只介绍到这里,可如vc一样的方式去使用内联,不过这便损失了gcc更为强大的功能。
在指令部分除了使用 AT&T标准语法之外,还可以有最多10个占位符:%0, %1, … , %9,他们出现的次序与操作数相对应,另外,可在%和数字之间插入字符w, h, b分别表示访问操作数中的低字,低字中的高字节和低字中的低字节。这里可能说的比较糊涂,不过没关系,介绍之后的部分自然会明白。
输出部分指示此内嵌汇编输出结果保存到什么变量中,这些变量通过占位符作为汇编语句中的操作数。当输出列表多于一个变量时,变量之间用逗号隔开,这些变量之间的修饰字符串中必须包含’=',来表示它是一个输出操作数,修饰字符稍微会做详细说明。
输入部分看名字就知道是做输入之用,语法格式也与输出部分相同,唯一缺少的就是那个修饰的符号’='。
到这里详细说一下修饰字符,修饰字符很多,这里仅仅介绍常用修饰符。
1、寄存器绑定:这类修饰符修饰的变量跟某中寄存器绑定,随后的操作中,可直接操作相应的寄存器。
绑定寄存器
EAX, EBX, ECX, EDX 任意一个
EAX, EBX, ECX, EDX, ESI, EDI 任意一个
被修饰是64位变量,要与%EAX,%EDX联合绑定
另外,如果该寄存器已经被绑定,编译器会在合适的地方push到堆栈,使用之后再回复此寄存器。
2、输出变量修饰
除了以上修饰符,还有一些只用于修饰输出变量,简单介绍如下:
输出变量不能和输入变量共用同一个寄存器
输出变量只写
先将输出变量预先读入到对应寄存器
gcc 内联汇编规范最后一个部分是破坏描述,不论做什么操作,基本都需要寄存器的参与,对于只有c代码的程序,编译器保护寄存器不会被不同模块写乱,但是对于内 联汇编,我们可能修改某些寄存器而破坏了gcc原本保护的寄存器,所以内联汇编时我们需要告诉编译器哪些寄存器使我们所需要改变的,这里破坏描述符由逗号 隔开的字符串组成,每个字符串描述一种情况,一般是寄存器名,另外还有”memory”-内存破坏描述符,内存描述符为了将寄存器保存的变量内容及时写回 到内存中去,避免在寄存器中存有多份不同拷贝,与c++关键字volatile类似。
到这里简要介绍了gcc内联汇编的部分语法,接下来举例说明此用法:
int main()
int sum = 0;
int var1 = 20;
int var2 = 15;
asm volatile( &movl %1, %0\n\t&
&addl %2, %0\n\t&
:&+a&(sum)
:&r&(var1), &r&(var2));
printf(&result is %d\n&, sum);
可以看到,在语句模板部分出现了占位符,其中 0,1,2 根据变量出现的次数依次为sum, var1, var2,所以,movl %1, %0 表示把var1存入sum,addl %2, %0表示把var2与sum相加结果存入sum,后面描述部分都比较简单,因为addl语句的关系,需要对%0先读其值后计算,所以需要使用描述 符”+”。
当然,内联汇编只是汇编跟c结合的一种方式,还有一种就是直接把汇编编译成目标文件,再跟c直接链接到一起,这里并没有什么新的东西,仅仅写一个AT&T汇编的例子:
#file Assembler.s
.section .text
.globl _mulTwo
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
mull 12(%ebp)
movl %ebp, %esp
这里汇编仅仅实现一个函数,并通过.globl导出符号,这里加下划线的原因是因为Windows的符号规则,之前已有说明。
/* file testAssembler.c*/
/** 由于c必须声明,这里仅仅对汇编函数做一个c声明 */
int mulTwo(int, int);
int main()
printf(&%d\n&, mulTwo(3, 5));
测试的c代码只需要定义一个汇编的函数声明即可使用。编译命令可以分别编译成目标文件再链接,也可直接使用 gcc testAssembler.c Assembler.s 编译之,对于反过来回调,汇编代码调用c代码,因为之前在汇编结尾已多次使用exit函数,这里便不再举例,同时,MASM语法的原理也相同,仅换了一套 编译命令而已。
from:&/content/16/128.shtml
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:628193次
积分:6580
积分:6580
排名:第2993名
原创:11篇
转载:572篇
评论:38条
(3)(1)(1)(2)(22)(14)(2)(1)(3)(8)(4)(7)(23)(2)(36)(24)(4)(4)(2)(1)(3)(7)(5)(20)(2)(8)(3)(4)(5)(2)(19)(6)(2)(1)(2)(3)(12)(32)(56)(44)(11)(36)(10)(22)(26)(2)(46)(29)(7)内联汇编跪求解答,该如何解决 - C++当前位置:& &&&内联汇编跪求解答,该如何解决内联汇编跪求解答,该如何解决&&网友分享于:&&浏览:0次内联汇编跪求解答输入字符串,转化大小写。
原代码是这样的:
#include&&stdio.h&
int&main()
char&string[128];
gets(string);
isletter1:
cmp&al,&'a'
cmp&al,&'z'
mov&ecx,&1
isletter2:
cmp&al,&'A'
cmp&al,&'Z'
mov&ecx,&1
mov&ecx,&0
lea&edx,&string
loopStart:
mov&al,&byte&ptr&ds:[edx]
test&al,&al
call&isletter1
test&ecx,&ecx
sub&byte&ptr&ds:[edx],&'a'-'A'
jmp&nextChar
call&isletter2
test&ecx,&ecx
jz&nextChar
add&byte&ptr&ds:[edx],&'a'-'A'
jmp&loopStart
puts(string);
可以运行,但是我需要用汇编语言读数,并且后期要循环方便输入多个字符串。
所以我改了下,把gets()函数写进_asm&:
#include&&stdio.h&
int&main()
char&string[128];
char&format[]&=&"%s";
lea&eax,string &;
push&eax &;
lea&eax,format &;
push&eax &;
call&scanf_s &;
add&esp,8 &;
isletter1:
cmp&al,&'a'
cmp&al,&'z'
mov&ecx,&1
isletter2:
cmp&al,&'A'
cmp&al,&'Z'
mov&ecx,&1
mov&ecx,&0
lea&edx,&string
loopStart:
mov&al,&byte&ptr&ds:[edx]
test&al,&al
call&isletter1
test&ecx,&ecx
sub&byte&ptr&ds:[edx],&'a'-'A'
jmp&nextChar
call&isletter2
test&ecx,&ecx
jz&nextChar
add&byte&ptr&ds:[edx],&'a'-'A'
jmp&loopStart
add&esp,4;
为什么这样就不能打印结果了。。该怎么改。。坐等。。跪谢!------解决方案--------------------scanf_s还要加一个参以表明最多读取多少位字符.
printf还要有参数format.
以下把LZ程序改为在VS2010中汇编调用scanf_s和printf的写法:
#include&&stdio.h&
int&main()
&&char&string[128];
&&char&format[]&=&"%s";
&&&&push&7fH
&&&&lea&eax,[string] &;
&&&&push&eax &;
&&&&lea&eax,[format] &;
&&&&push&eax &;
&&&&call&dword&ptr&scanf_s &;
&&&&add&esp,8 &;
&&&&jmp&entry
isletter1:
&&&&cmp&al,&'a'
&&&&&&jl&nex
&&&&&&cmp&al,&'z'
&&&&&&jg&nex
&&&&&&mov&ecx,&1
isletter2:
&&&&cmp&al,&'A'
&&&&&&jl&nex
&&&&&&cmp&al,&'Z'
&&&&&&jg&nex
&&&&&&mov&ecx,&1
&&&&mov&ecx,&0
&&&&lea&edx,&[string]
loopStart:
&&&&mov&al,&byte&ptr&ds:[edx]
&&&&test&al,&al
&&&&&&jz&end
&&&&&&call&isletter1
&&&&&&test&ecx,&ecx
&&&&&&jz&test2
&&&&&&sub&byte&ptr&ds:[edx],&'a'-'A'
&&&&&&jmp&nextChar
&&&&call&isletter2
&&&&&&test&ecx,&ecx
&&&&&&jz&nextChar
&&&&&&add&byte&ptr&ds:[edx],&'a'-'A'
&&&&inc&edx
&&&&&&jmp&loopStart
&&&&lea&eax,[string] &;
&&&&push&eax &;
&&&&lea&eax,[format];
&&&&call&dword&ptr&
&&&&add&esp,4;
&&return&0;
12345678910
12345678910
12345678910 上一篇:下一篇:文章评论相关解决方案 12345678910 Copyright & &&版权所有查看: 2862|回复: 3
关于内联汇编。
主题帖子精华
中级会员, 积分 250, 距离下一级还需 250 积分
在线时间0 小时
关于这段代码:
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
if(((*(vu32*)appxaddr)&0x2FFE0000)==0x) //检查栈顶地址是否合法.
jump2app=(iapfun)*(vu32*)(appxaddr+4);
//用户代码区第二个字为程序开始地址(复位地址)
MSR_MSP(*(vu32*)appxaddr);
//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
jump2app();
//跳转到APP.
__asm void MSR_MSP(u32 addr)&
& & MSR MSP, r0
//set Main Stack value
& & BX r14
app堆栈顶地址是如何通过内联汇编进行堆栈的更新的? 那个顶地址怎么传进去的? 疑惑...................
成功的欲望强烈到一定程度的时候足够征服世界。
主题帖子精华
金钱102518
在线时间608 小时
汇编强制设置咯.
应该就是等效寄存器赋值类似的.
我是开源电子网站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子
主题帖子精华
中级会员, 积分 250, 距离下一级还需 250 积分
在线时间0 小时
回复【2楼】正点原子:
---------------------------------
原子哥,那可以这样写吗?
__asm&void&MSR_MSP(void)&
{
&&&&MSR&MSP,&r0&=*(vu32*)appxaddr
&&&&BX&r14
}
MSR_MSP();
成功的欲望强烈到一定程度的时候足够征服世界。
主题帖子精华
金钱102518
在线时间608 小时
你试试吧,貌似汇编不支持这种写法吧.
我没怎么用STM32的汇编,不是很熟,不好意思.
我是开源电子网站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺:
微信公众平台:正点原子
Powered by内联汇编方式:
内联汇编方式两个作用:
1、程序的某些关键代码直接用汇编语言编写可提高代码的执行效率。
2、有些操作无法通过高级语言实现,或者实现起来很困难,必须借助汇编语言达到目的。 使用方式:
_asm{汇编语句}
2、_asm语句
1 #include&iostream&
2 using namespace
3 void print(){
cout&&"External Function"&&
6 class A{
void print(){
cout&&"A::Member Function"&&
<span style="color: #
<span style="color: # };
<span style="color: # typedef void(*fun)();
<span style="color: # int main(){
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
v = (void *)&
<span style="color: #
<span style="color: #
<span style="color: #
//用内联汇编方式获取类的非静态成员函数的入口地址。
<span style="color: #
<span style="color: #
//将A::print的偏移地址送到eax寄存器中
<span style="color: #
lea eax,A::print
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
return <span style="color: #;
<span style="color: # }
&上述print函数并没有访问类A的成员属性。
在VisualC++中,类的成员函数在调用之前,编译器生成的汇编码 将对象的首地址送入到寄存器ecx中。因此,如果通过内联汇编码 获取了类的非静态成员函数的入口地址,在调用该函数之前, 还应该将类对象的首地址送到寄存器ecx中。只有这样才能保证 正确调用
1 #include&iostream&
2 using namespace
3 typedef void(*fun)();
5 class A{
A(){i=<span style="color: #;}
void print(){
<span style="color: #
<span style="color: #
<span style="color: # };
<span style="color: # void Invoke(A &a){
<span style="color: #
<span style="color: #
<span style="color: #
lea eax,A::print
<span style="color: #
<span style="color: #
//将对象地址送入ecx寄存器
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # }/*
<span style="color: # void Invoke(A a){
<span style="color: #
<span style="color: #
<span style="color: #
lea eax,A::print
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: #
<span style="color: # }*/
<span style="color: # int main(){
<span style="color: #
<span style="color: #
Invoke(a);
<span style="color: # }
阅读(...) 评论()}

我要回帖

更多关于 汇编获取系统时间 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信