asm学习

参考:
http://thinkingeek.com/2013/01/10/arm-assembler-raspberry-pi-chapter-2/
先上代码。

/*  first.s  */

.global main        /* main is our entry point and must be global*/

main:               /* This is main */
/* whitespace is ignored at the beginning of the line  */
    mov r0, #2      /* Put a 2 inside the register r0 */
    bx lr           /* Return from main. bx means branch & exchange*/

写完.s源文件之后,可以通过as命令编译,然后用gcc。但有些麻烦,这里最好写到当前目录的Makefile里面,直接make命令就弄好了。

cqq@snort-ids:~/repos/asm_demo$ make
Makefile:8: *** missing separator (did you mean TAB instead of 8 spaces?).  Stop.
cqq@snort-ids:~/repos/asm_demo$ vi Makefile
cqq@snort-ids:~/repos/asm_demo$ make
as -o first.o first.s
gcc -o first first.o
cqq@snort-ids:~/repos/asm_demo$ ls
Makefile  first  first.o  first.s  sum01.s
cqq@snort-ids:~/repos/asm_demo$ ./first ; echo $?
2
cqq@snort-ids:~/repos/asm_demo$ cat Makefile
# Makefile
### $@: the whole params that passes to the script
### $+:

all: first

first: first.o
    gcc -o $@ $+

first.o: first.s
    as -o $@ $<

clean:
    rm -rf first *.o

注意:Makefile里面的是TAB,而不是8个空格。
Makefile很方便,直接make命令就可以得到可执行文件,然后想要清除的时候,直接make clean即可。

cqq@snort-ids:~/repos/asm_demo/asm_sum01$ make clean
rm -rf sum01 *.o

比如这段汇编代码,把2传给r0(Raspbery Pi 有16个整型寄存器r0~r15,可容纳32bits)。这样程序退出之后,r0中存储的值就是2。于是通过

cqq@snort-ids:~/repos/asm_demo$ ./first; echo $?
2

可以得到这个值。

退出状态

$? 可以获取上一个命令的退出状态。所谓退出状态,就是上一个命令执行后的返回结果。退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1。不过,也有一些命令返回其他值,表示不同类型的错误。
参考:
http://c.biancheng.net/cpp/view/2739.html

然后可以来这么一段代码,将r1和r2的值装载到r0上,然后最后程序退出,返回r0的值。

/* sum01.s */

.global main

main:
    mov r1, #3             /* r1 <- 3  */
    mov r2, #4             /* r2 <- 4  */
    add r0, r1, r2         /* r0 <- r1 + r2 */
    bx lr

然后得到返回值为7。

cqq@snort-ids:~/repos/asm_demo/asm_sum01$ ./sum01 ;echo $?
7

当然,我们也可以重用r0寄存器,不劳r2费心。

/* sum02.s */

.global main

main:
    mov r0, #3             /* r0 <- 3  */
    mov r1, #4             /* r1 <- 4  */
    add r0, r0, r1         /* r0 <- r0 + r1 */
    bx lr

同样可以得到预期的结果。

cqq@snort-ids:~/repos/asm_demo/asm_sum02$ ./sum02 ; echo $?
7

前两章里面,我们学习了如何使用mov指令将值传给寄存器(registers),然后使用add指令将两个registers中的值相加。如果我们的处理器只能在registers上操作那就太局限了。

Memory(内存)

这节主要将两个操作。”load from memory to register”以及”store from register to memory”。这两个操作,叫做loadstore。有很多方式load和store,但是今天只讨论两个ldrstr
从memory中load数据有点复杂,因为,因为我们要谈论addresses。

Addresses

要访问数据,我们就要给它一个名字,不然我们就不能指代我们想要哪一部分数据。然而当然一个计算机并不能给在内存中的每一片数据都赋一个名字。好吧,其实也有一个可以算是名字的,那就是地址(addresses)。地址就是一个数字,在ARM中就是一个32位的数字,用来标识在内存中的每个字节(8 bits)。


内存就像一串字节,其中每个字节都有其自己的地址。

When loading or storing data from/to memory,我们需要计算地址。可以通过很多方式来计算地址。这每一种方式都叫做一个寻址方式。ARM有好几个寻址模式,现在我们只讲通过register来寻址(addressing through a register)。

在ARM平台,ARM有32位的整型registers,并且memory的地址也是32位的数字。这意味着我们可以在register中存放一个内存地址!

只要我们在register中存放了一个内存地址,我们就可以用那个register来load或者store一些数据(因为这个地址对应着memory中的位置,既可以从那里读,也可以将数据写到那里)。

数据(Data)

//TODO

你可能感兴趣的:(汇编)