2.汇编代码的简单实现

2.汇编代码的简单实现

  1. 使用汇编的原因很简单,就是汇编代码的高效。在机器启动的时候,利用汇编的高效,对硬件进行初始化,为加载内核,提供条件。
  2. 目前常用的ARM汇编指令有两种:

    *ARM标准汇编:适用于ARM公司的汇编器,适合在Windows平台下使用。

    *GNU汇编:使用与GNU交叉编译工具链中的汇编器,适合于Linux平台开发。

3.汇编程序框架:注意下面的操作环境是Redhat 6.4 + eclipse C/C++ +CDT插件。

汇编代码的基本框架

?

汇编用到的地方,启动代码,效率要求高效的地方。

上面是启动代码的框架。

下面搭建框架:

start.S:

.text

.global _start

_start:

????mov r2,#2

????mov r3,#3

Makefile:

all : start.o

????arm-linux-ld -Tgboot.lds -o start.elf $^

%.o : %.S

????arm-linux-gcc -g -o [email protected] $^ -c

clean:

????rm *.o *.elf

简单工程的运行的结构:

链接器脚本:

Gboot.lds:

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS {

????. = 0x50008000;

????

????. = ALIGN(4);

????.text :

????{

????start.o (.text)

????*(.text)

????}

?

????. = ALIGN(4);

????.data :

????{

????*(.data)

????}

????

????. = ALIGN(4);

????bss_start = .;

????.bss :

????{

????*(.bss)

????}

????bss_end = .;

}

运行的结果:

接下来是汇编代码的操作实现:

mov r1,#6

mov r2,r1

mov r3,#10

@mvn:传值取反的值

????mvn r0,#4 @r0:4取反变为-5

????mvn r1,#0b111000

????mvn r2,r1 @r2:0b111000

Sub的实例:

?

Add的实例:

当然,我们也可以在执行的时候指定参数的值:如下图,我们指定了r0=44,r2=66.

运行了之后:

?

And的实例;

Bic的实例:第三个数是源码,源码位为1的,对应的位清0,源码位是0的,对应的位不变。

从上面的执行结果看到,r1的最高位,和最低两位的1,对应源码位的值都是1,所以,被清0,中间四位,对应源码的四个0,保持不变1010.所以最后输出了0b101000.

?

  1. 比较指令

    Cmp指令的操作:比较的结果不会保持,回去影响cpsr对应的位:N或Z位。

    我们可以看到r1-1=1是正数,cpsr的最高位四位2=0010,N,Z位都是0.

    这里r1-3=-1,cpsr的最高四位8=1000,即是N位被置为1,表示结果是负数。

    这里r1-2=0,cpsr的次高位被置为1,表示两个数相等。

    Txt指令的操作:测试位、按位与,结果为0 ,Z位被置为1,结果不为0,Z位置为0

    按位与之后的值不为0,所以cpsr的Z位不会被置为1.

    按位与之后的结果是为0的,所以cpsr的Z位被置1.结果高四位的值是4.

  2. 跳转指令:

    B指令:

    上面的例子中,gt表示大于的时候跳转,6>5所以跳转到标签branch1处执行。不会执行add r3,r1,r2.

    上面,跳转的条件不成立,顺序执行,不跳转。但是会顺序执行,所以加个b end跳转到end,执行空操作。

    ?

    ?

    ?

    ?

    ?

    ?

    Bl:带链接的跳转:

    Lr:

    反汇编的代码:

    由上面看到lr保存的是bl返回来后的下一条地址,把他赋值给pc指针进行跳转。

    ?

  3. 移位指令:
  4. Lsl左移指令:

    11左移两位:1100

  5. ror循环右移:

    循环右移,最低位的1,被循环移动到了最高位。

    ?

    ?

    ?

    ?

    ?

  6. 程序状态字访问指令。

    在GNU汇编中,我们不允许上面的 指令来操作访问我们的程序字状态寄存器指令,所以我们需要将他们的值移出,再进行操作访问,修改等,操作完还要移进去。所以就设计到两个指令:MSR和MRS指令。搬出mrs,搬回去msr。

    执行了之后:

    最后:

    我们就是得通过上面的操作来改变cpsr里的值的。

  7. 存储器访问指令:

    上面的都是核里面的指令,内存是通过存储器访问质指令。

    Ldr指令:内存保存到寄存器

    Str指令:寄存器保存到内存。

    我们把r1设置成了开发板内存的地址,如上图,接下来在memory里创建一个监控的地址:

    接下来看看运行了上面的指令后的变化:如下图,我们的0xff已经被保存到了0x50008000.

    下面是ldr:

    R2的值就是存进r0里的值,被取出来了。

    ?

    ?

    这个汇编操作的工程代码:

    .text

    .global _start

    _start:

    [email protected]和str的操作

    ????mov r0,#0xff

    ????str r0,[r1]

    ????ldr r2,[r1]

    [email protected]程序状态字寄存器访问

    ????mrs r0,cpsr

    ????orr r0,#0b100

    ????msr cpsr,r0

    [email protected]:循环右移

    ????mov r1,#0b11

    ????mov r1,r1,ror#1

    [email protected]:左移

    ????mov r1,#0b11

    ????mov r1,r1,lsl#2

    [email protected]指令:带链接跳转

    ????bl func1

    [email protected]指令:

    ????mov r1,#6

    ????mov r2,#7

    ????cmp r1,r2

    ????bgt [email protected]表示大于的时候跳转

    ????add r3,r1,r2

    ????b end

    func1:

    ????mov r1,#23

    ????mov pc,[email protected]函数的返回,固定格式。

    ?

    branch1:

    ????sub r3,r1,r2

    end:

    ????nop

    [email protected]指令:

    ????mov r1,#0b101

    ????tst r1,#0b01

    ?

    ????mov r1,#0b101

    ????tst r1,#0b10

    [email protected]指令的操作:

    ????mov r1,#2

    ????cmp r1,#1

    ?

    ????mov r1,#2

    ????cmp r1,#3

    ?

    ????mov r1,#2

    ????cmp r1,#2

    [email protected]:位清除指令

    ????mov r1,#0b1101011

    ????bic r2,r1,#0b1000011

    [email protected]的用法:逻辑与

    ????mov r1,#5

    ????and r2,r1,#0

    ?

    ????mov r1,#5

    ????and r2,r1,#1

    [email protected]:加法:

    ????add r1,r0,r2

    [email protected]:减法,注意被减数不能是立即数

    ????mov r2,#4

    ????sub r0,r2,#2

    ????mov r1,#3

    ????sub r3,r1,r0

    [email protected]这是注释,mov指令

    ????mov r1,#6

    ????mov r2,r1

    ????mov r3,#10

    [email protected]:传值取反的值

    ????mvn r0,#4 @r0:4取反变为-5

    ????mvn r1,#0b111000

    ????mvn r2,r1 @r2:0b111000

时间: 2024-10-10 05:29:12

2.汇编代码的简单实现的相关文章

C++内嵌汇编代码,简单文件加密

#include <iostream> #include <fstream> using namespace std; int main(int argc, char* argv[]){ if(argc < 3){ cout<<"Usage: Project infile outfile"<<endl; return -1; } const int BUFSIZE = 2000; char buf[BUFSIZE]; unsigne

通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

实验一:通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的 学号:20135114 姓名:王朝宪 注: 原创作品转载请注明出处   <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 1 1)实验部分(以下命令为实验楼64位Linux虚拟机环境下适用,32位Linux环境可能会稍有不同) 使用 gcc –S –o main.s main.c -m32 命令编译成汇编代码,如下代码中的数字请自行修改以防与

理解计算机的工作方式——通过汇编一个简单的C程序并分析汇编代码

Author: 翁超平 Notice:原创作品转载请注明出处 See also:<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000  本文通过汇编一个简单的C程序,并分析汇编代码,来理解计算机是如何工作的.整个过程都在实验楼上完成,感兴趣的读者可以通过上面给出的课程链接自行动手学习.以下是实验过程和结果. 一.操作步骤 1.首先在通过vim程序建立main.c文件.代码如下: 图1 2.使用如下命令将main.c编

一个简单C程序的汇编代码分析

几个重要的寄存器 eip - 用于存放当前所执行的指令地址 esp - 栈(顶)指针寄存器 ebp - 基址(栈底)指针寄存器 简单的C程序 1 int g(int x) 2 { 3 return x + 10; 4 } 5 6 int f(int x) 7 { 8 return g(x); 9 } 10 11 int main(void) 12 { 13 return f(7) + 5; 14 } 汇编代码分析 1 g: 2 pushl %ebp 3 movl %esp, %ebp 4 :下面

11.汇编代码简单操作

11.汇编代码简单操作 使用汇编的原因很简单,就是汇编代码的高效.在机器启动的时候,利用汇编的高效,对硬件进行初始化,为加载内核,提供条件. 目前常用的ARM汇编指令有两种: *ARM标准汇编:适用于ARM公司的汇编器,适合在Windows平台下使用. *GNU汇编:使用与GNU交叉编译工具链中的汇编器,适合于Linux平台开发. 3.汇编程序框架:注意下面的操作环境是Redhat 6.4 + eclipse C/C++ +CDT插件. 汇编代码的基本框架 ? 汇编用到的地方,启动代码,效率要求

简单C程序生成的汇编代码分析

首先给出完整的C代码: int g(int x){ return x+11;}int f(int x){ return g(x);}int main(void){ return f(8)+1;} 使用命令:gcc –S –o hw001.s hw001.c -m32 对应生成的IA32汇编代码如图所示: 暂不分析以“.”开头的行,得到程序如下: g: pushl %ebp movl %esp ,%ebp movl 8(%ebp) ,%eax addl $11 ,%eax popl %ebp re

C编译器剖析_6.3.1 汇编代码生成_由中间指令产生汇编代码的主要流程

6.3.1  由中间指令产生汇编代码的主要流程 在这一小节,我们可把关注的焦点放在"如何把某条中间代码翻译成汇编代码"上.UCC编译器的中间代码是如下所示的四元式,包括运算符和3个操作数. <运算符opcode,目的操作数DST,源操作数SRC1,源操作数SRC2> 当然有些中间代码只需要用到opcode和DST就可以了,例如,无条件跳转指令"goto  BB2;"就不需要SRC1和SRC2.为了便于汇编代码的生成,UCC编译器在ucl\X86Linux

20145311利用gdb调试汇编代码

利用GDB调试汇编代码 首先编写c语言原代码,我使用的是同学分析过的代码 #include<stdio.h>short addend1 = 1;static int addend2 = 2;const static long addend3 = 3; static int g(int x){    return x + addend1;} static const int f(int x){    return g(x + addend2);} int main(void){    retur

C编译器剖析_6.3.5 汇编代码生成_为类型转换产生汇编代码

6.3.5  为类型转换产生汇编代码 在这一小节中,我们来讨论一下整型和浮点型之间的类型转换.有些类型转换并不需要在汇编层次进行数据转换,例如int和unsigned  int之间的转换只是改变了表达式的类型,对数据本身并无影响,以下表达式"(unsigned int) a"对应的二进制数据为0xFFFFFFFF,而表达式"a"对应的二进制数据也为0xFFFFFFFF.但对相同内容的二进制数据来说,进行"有符号整数的右移"和"无符号整数