本帖最后由 新ちゃん 于 2020-8-20 22:57 编辑
Absolute addressingThe following example shows how to load an absolute address: - .section .text
- .globl _start
- _start:
- lui a1, %hi(msg) # load msg(hi)
- addi a1, a1, %lo(msg) # load msg(lo)
- jalr ra, puts
- 2: j 2b
- .section .rodata
- msg:
- .string "Hello World\n"
复制代码
which generates the following assembler output and relocations as seen by objdump: - 0000000000000000 <_start>:
- 0: 000005b7 lui a1,0x0
- 0: R_RISCV_HI20 msg
- 4: 00858593 addi a1,a1,8 # 8 <.L21>
- 4: R_RISCV_LO12_I msg
复制代码
Relative addressingThe following example shows how to load a PC-relative address: - .section .text
- .globl _start
- _start:
- 1: auipc a1, %pcrel_hi(msg) # load msg(hi)
- addi a1, a1, %pcrel_lo(1b) # load msg(lo)
- jalr ra, puts
- 2: j 2b
- .section .rodata
- msg:
- .string "Hello World\n"
复制代码
which generates the following assembler output and relocations as seen by objdump:
- 0000000000000000 <_start>:
- 0: 00000597 auipc a1,0x0
- 0: R_RISCV_PCREL_HI20 msg
- 4: 00858593 addi a1,a1,8 # 8 <.L21>
- 4: R_RISCV_PCREL_LO12_I .L11
复制代码
Load ImmediateThe following example shows the li psuedo instruction which is used to load immediate values: - .section .text
- .globl _start
- _start:
- .equ CONSTANT, 0xcafebabe
- li a0, CONSTANT
复制代码
which generates the following assembler output as seen by objdump:
- 0000000000000000 <_start>:
- 0: 00032537 lui a0,0x32
- 4: bfb50513 addi a0,a0,-1029
- 8: 00e51513 slli a0,a0,0xe
- c: abe50513 addi a0,a0,-1346
复制代码
Load AddressThe following example shows the la psuedo instruction which is used to load symbol addresses: - .section .text
- .globl _start
- _start:
- la a0, msg
- .section .rodata
- msg:
- .string "Hello World\n"
复制代码
which generates the following assembler output and relocations as seen by objdump: - 0000000000000000 <_start>:
- 0: 00000517 auipc a0,0x0
- 0: R_RISCV_PCREL_HI20 msg
- 4: 00850513 addi a0,a0,8 # 8 <_start+0x8>
- 4: R_RISCV_PCREL_LO12_I .L11
复制代码
ConstantsThe following example shows loading a constant using the %hi and %lo assembler functions. - .equ UART_BASE, 0x40003000
- lui a0, %hi(UART_BASE)
- addi a0, a0, %lo(UART_BASE)
复制代码
This example uses the li pseudoinstruction to load a constant and writes a string using polled IO to a UART: - .equ UART_BASE, 0x40003000
- .equ REG_RBR, 0
- .equ REG_TBR, 0
- .equ REG_IIR, 2
- .equ IIR_TX_RDY, 2
- .equ IIR_RX_RDY, 4
- .section .text
- .globl _start
- _start:
- 1: auipc a0, %pcrel_hi(msg) # load msg(hi)
- addi a0, a0, %pcrel_lo(1b) # load msg(lo)
- 2: jal ra, puts
- 3: j 3b
- puts:
- li a2, UART_BASE
- 1: lbu a1, (a0)
- beqz a1, 3f
- 2: lbu a3, REG_IIR(a2)
- andi a3, a3, IIR_TX_RDY
- beqz a3, 2b
- sb a1, REG_TBR(a2)
- addi a0, a0, 1
- j 1b
- 3: ret
- .section .rodata
- msg:
- .string "Hello World\n"
复制代码
Floating-point rounding modesFor floating-point instructions with a rounding mode field, the rounding mode can be specified by adding an additional operand. e.g. fcvt.w.s with round-to-zero can be written as fcvt.w.s a0, fa0, rtz. If unspecified, the default dyn rounding mode will be used. Supported rounding modes are as follows (must be specified in lowercase): - rne: round to nearest, ties to even
- rtz: round towards zero
- rdn: round down
- rup: round up
- rmm: round to nearest, ties to max magnitude
- dyn: dynamic rounding mode (the rounding mode specified in the frm field of the fcsr register is used)
Control and Status RegistersThe following code sample shows how to enable timer interrupts, set and wait for a timer interrupt to occur: - .equ RTC_BASE, 0x40000000
- .equ TIMER_BASE, 0x40004000
- # setup machine trap vector
- 1: auipc t0, %pcrel_hi(mtvec) # load mtvec(hi)
- addi t0, t0, %pcrel_lo(1b) # load mtvec(lo)
- csrrw zero, mtvec, t0
- # set mstatus.MIE=1 (enable M mode interrupt)
- li t0, 8
- csrrs zero, mstatus, t0
- # set mie.MTIE=1 (enable M mode timer interrupts)
- li t0, 128
- csrrs zero, mie, t0
- # read from mtime
- li a0, RTC_BASE
- ld a1, 0(a0)
- # write to mtimecmp
- li a0, TIMER_BASE
- li t0, 1000000000
- add a1, a1, t0
- sd a1, 0(a0)
- # loop
- loop:
- wfi
- j loop
- # break on interrupt
- mtvec:
- csrrc t0, mcause, zero
- bgez t0, fail # interrupt causes are less than zero
- slli t0, t0, 1 # shift off high bit
- srli t0, t0, 1
- li t1, 7 # check this is an m_timer interrupt
- bne t0, t1, fail
- j pass
- pass:
- la a0, pass_msg
- jal puts
- j shutdown
- fail:
- la a0, fail_msg
- jal puts
- j shutdown
- .section .rodata
- pass_msg:
- .string "PASS\n"
- fail_msg:
- .string "FAIL\n"
复制代码本篇完
|