这些操作码有什么作用?
What do these Opcodes do?
我正在学习 Western Digital 的 RISC-V 汇编教程。我对汇编编程比较陌生。所以我有几个需要澄清的问题,而且我似乎找不到真正的虚拟友好教程。
这是有问题的代码 on GITHub。
# SPDX-License-Identifier: Unlicense
# Copyright (c) 2018 Western Digital Corporation or its affiliates.
.section .text
.align 2
.globl setupGPIO
.include "memory_map.inc"
.include "gpio.inc"
setupGPIO:
addi sp, sp, -16 # Allocate Stack Frame
#First Question
sw ra, 12(sp) # Save return address onto the stack
li t0, GPIO_CTRL_ADDR # Load the base GPIO address
li t1, GPIO_RGB_PINS # Get the RGP Pins offset
sw t1, GPIO_OUTPUT_EN(t0) # Enable RGB pins as output pins
sw t1, GPIO_OUTPUT_XOR(t0) # Set the XOR to that the pins are Active High
#Second Question
sw x0, GPIO_OUTPUT_VAL(t0) # Set all writable GPIO pins to zero
#Third Question
lw ra, 12(sp) # Restore the return address
addi sp, sp, 16 # Deallocate stack frame
ret
那么,我的问题是:
12在做什么?我认为堆栈指针已经在前面的指令中移动了 16 位。我通常对为什么在内存中向下移动 16 位,然后再添加 12 位感到困惑。
此外,此语法在 x86 中是否表示与 [eax+12]
?
相同的内容
目标操作数一直在左边,难道只有x0
寄存器才向后?
我注意到我们根本没有使用堆栈指针,我们真的需要这样做吗?另外,sw
和 lw
有什么区别?它们都被使用过,但我不确定它们的作用是什么,也不知道为什么一个会比另一个被使用。
1) 栈指针减16为当前帧在栈上预留space。为了将内容存储到保留的 space 中,您向递减的堆栈指针添加一个偏移量(在本例中为 12)。
2) sw
将一个单词(在本例中为值 0,x0 始终包含)从寄存器存储到内存,你是对的(IMO)参数的顺序向后比较到语法的其余部分。
3) a) 我们已经使用堆栈指针来保存和恢复 return 地址,在这个本身并不调用的小函数中不需要它,但作为标准函数进入和退出的样板,这是一个有用的模式。堆栈用于存储不适合寄存器(或需要在堆栈上以支持递归)的局部变量,学习如何使用它是他们在这里向您展示的内容的一部分。
3 b) sw
将寄存器中的值存储到内存中,lw
从内存中加载值并存储到寄存器中。在设备驱动程序中,内存位置是您与设备通信的方式 - 存储到内存可以让您向设备提供信息(数据或控制信息),从内存加载是您从设备读取信息的方式。
我正在学习 Western Digital 的 RISC-V 汇编教程。我对汇编编程比较陌生。所以我有几个需要澄清的问题,而且我似乎找不到真正的虚拟友好教程。
这是有问题的代码 on GITHub。
# SPDX-License-Identifier: Unlicense
# Copyright (c) 2018 Western Digital Corporation or its affiliates.
.section .text
.align 2
.globl setupGPIO
.include "memory_map.inc"
.include "gpio.inc"
setupGPIO:
addi sp, sp, -16 # Allocate Stack Frame
#First Question
sw ra, 12(sp) # Save return address onto the stack
li t0, GPIO_CTRL_ADDR # Load the base GPIO address
li t1, GPIO_RGB_PINS # Get the RGP Pins offset
sw t1, GPIO_OUTPUT_EN(t0) # Enable RGB pins as output pins
sw t1, GPIO_OUTPUT_XOR(t0) # Set the XOR to that the pins are Active High
#Second Question
sw x0, GPIO_OUTPUT_VAL(t0) # Set all writable GPIO pins to zero
#Third Question
lw ra, 12(sp) # Restore the return address
addi sp, sp, 16 # Deallocate stack frame
ret
那么,我的问题是:
12在做什么?我认为堆栈指针已经在前面的指令中移动了 16 位。我通常对为什么在内存中向下移动 16 位,然后再添加 12 位感到困惑。
此外,此语法在 x86 中是否表示与[eax+12]
? 相同的内容
目标操作数一直在左边,难道只有
x0
寄存器才向后?我注意到我们根本没有使用堆栈指针,我们真的需要这样做吗?另外,
sw
和lw
有什么区别?它们都被使用过,但我不确定它们的作用是什么,也不知道为什么一个会比另一个被使用。
1) 栈指针减16为当前帧在栈上预留space。为了将内容存储到保留的 space 中,您向递减的堆栈指针添加一个偏移量(在本例中为 12)。
2) sw
将一个单词(在本例中为值 0,x0 始终包含)从寄存器存储到内存,你是对的(IMO)参数的顺序向后比较到语法的其余部分。
3) a) 我们已经使用堆栈指针来保存和恢复 return 地址,在这个本身并不调用的小函数中不需要它,但作为标准函数进入和退出的样板,这是一个有用的模式。堆栈用于存储不适合寄存器(或需要在堆栈上以支持递归)的局部变量,学习如何使用它是他们在这里向您展示的内容的一部分。
3 b) sw
将寄存器中的值存储到内存中,lw
从内存中加载值并存储到寄存器中。在设备驱动程序中,内存位置是您与设备通信的方式 - 存储到内存可以让您向设备提供信息(数据或控制信息),从内存加载是您从设备读取信息的方式。