对本文有疑问可以加微信 Tutor_0914
联系。也可以访问我的个人辅导网站 :
文章目录
1 数组
// Read 10 numbers into an array
// then print the numbers which are
// larger than the last number read.
#include <stdio.h>
int main(void) {
int i, last_number;
int numbers[10] = { 0 };
i = 0;
while (i < 10) {
scanf("%d", &numbers[i]);
last_number = numbers[i];
i++;
}
i = 0;
while (i < 10) {
if (numbers[i] >= last_number) {
printf("%d\n", numbers[i]);
}
i++;
}
}
c语言对应的汇编
# Read 10 numbers into an array
# then print the numbers which are
# larger than the last number read.
# i in register $t0
# registers $t1, $t2 & $t3 used to hold temporary results
# t4 is the last value
main:
li $t0, 0 # i = 0
loop0:
bge $t0, 10, end0 # while (i < 10) {
li $v0, 5 # scanf("%d", &numbers[i]);
syscall # 输入的数字储存在v0中
mul $t1, $t0, 4 # calculate &numbers[i],一个int是4个bit
la $t2, numbers # 储存数组的首地址
add $t3, $t1, $t2 # 数组的首地址,加上i * 4,就是0号元素应该在的位置
sw $v0, ($t3) # store entered number in array,sw就是save word的意思。
# v0输入的值储存在t3地址
add $t4, $v0, 0 # also can be s0
addi $t0, $t0, 1 # i++;
j loop0 # }
end0:
li $t0, 0 # i = 0
loop1:
bge $t0, 10, end1 # while (i < 10) {
mul $t1, $t0, 4 # calculate &numbers[i]
la $t2, numbers #
add $t3, $t1, $t2 #
lw $a0, ($t3) # load numbers[i] into $a0
bge $a0, $t4, print # 如果大于等于,就需要去有输出的分支。
addi $t0, $t0, 1 # i++
j loop1 # }
print:
li $v0, 1 # printf("%d", numbers[i])
syscall
li $a0, '\n' # printf("%c", '\n');
li $v0, 11
syscall
addi $t0, $t0, 1 # i++ 在输出分支里继续增加控制变量。
j loop1 # }
end1:
jr $ra # return
.data
numbers:
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 # int numbers[10] = {0};
2 函数
2.1 sw和lw
主要是sw和lw,这两个指令在操作内存。
sw $v0, ($t3) # store entered number in array,sw就是save word的意思。
# v0输入的值储存在t3地址
lw $a0, ($t3) # load *t3 into $a0
2.2 ra
jr $ra
在一个函数里,ra储存的地址是该函数执行完之后,应该返回的地址。所以,该命令执行后,相当于将PC的值设置为ra里的地址值。跳转回去原本函数调用的位置。
2.3 函数使用的一些默认寄存器
存放函数输入参数的四个寄存器: $a0, $a1, $a2, $a3
返回值寄存器在 $v0
2.4 函数调用 jal
jal function set $ra to PC+4 and jumps to function
2.5 无参函数直接调用示例
2.6 无参有返回值
2.7 嵌套函数调用
学会将当前的ra值压入stack!
当又调用一个函数的时候,stack向低地址生长!
2.7.1 sp
当前的栈指针
2.7.2 fp
2.7.3 示例
#include <stdio.h>
int sum_product(int a, int b);
int product(int x, int y);
int main(void) {
int z = sum_product(10, 12);
printf("%d\n", z);
return 0;
}
int sum_product(int a, int b) {
int p = product(6, 7);
return p + a + b;
}
int product(int x, int y) {
return x * y;
}
对应的汇编
main:
addi $sp, $sp, -4 # move stack pointer down to make room
sw $ra, 0($sp) # save $ra on $stack
li $a0, 10 # sum_product(10, 12);
li $a1, 12
jal sum_product
move $a0, $v0 # printf("%d", z);
li $v0, 1
syscall
li $a0, '\n' # printf("%c", '\n');
li $v0, 11
syscall
lw $ra, 0($sp) # recover $ra from $stack
addi $sp, $sp, 4 # move stack pointer back up to what it was when main called
li $v0, 0 # return 0 from function main
jr $ra # return from function main
sum_product:
addi $sp, $sp, -12 # move stack pointer down to make room
sw $ra, 8($sp) # save $ra on $stack
sw $a1, 4($sp) # save $a1 on $stack
sw $a0, 0($sp) # save $a0 on $stack
li $a0, 6 # product(6, 7);
li $a1, 7
jal product
lw $a1, 4($sp) # restore $a1 from $stack
lw $a0, 0($sp) # restore $a0 from $stack
add $v0, $v0, $a0 # add a and b to value returned in $v0
add $v0, $v0, $a1 # and put result in $v0 to be returned
lw $ra, 8($sp) # restore $ra from $stack
addi $sp, $sp, 12 # move stack pointer back up to what it was when main called
jr $ra # return from sum_product
product: # product doesn't call other functions
# so it doesn't need to save any registers
mul $v0, $a0, $a1 # return argument * argument 2
jr $ra #
2.8 函数调用时假设不变量:
if function changes $sp, $fp, $s0..$s8
it restores their value
callers assume $sp, $fp, $s0..$s8
unchanged by call (jal)
a function may destroy the value of other registers e.g. $t0..$t9
callers must assume value in e.g.
t
0..
t0..
t0..t9 changed by call (jal)