一生一芯E4-c语言学习(待更新)
预处理
// a.c
#include <stdio.h>
#define MSG "Hello \
World!\n"
#define _str(x) #x
#define _concat(a, b) a##b
int main() {
printf(MSG /* "hi!\n" */);
#ifdef __riscv
printf("Hello RISC-V!\n");
#endif
_concat(pr, intf)(_str(RISC-V));
return 0;
}
运行gcc -E a.c,gcc过程分为预处理-编译-汇编-链接-E就是做到预处理这一步
_str _concat都是函数式宏定义
ifdef ... #endif条件编译指令:__riscv:这是一个 编译器内置的预定义宏,只有在「编译 RISC-V 架构的程序」时,编译器才会自动定义这个宏;在 x86/x64(电脑常用)、ARM 等架构下,这个宏是未定义的。我电脑运行后 直接跳过他。
运行指令后变为:
# 6 "a.c"
int main() {
printf("Hello World!\n" );
printf("RISC-V");
return 0;
}
verbose加入指令后会在终端输出两类关键信息:
1.gcc自身的版本,编译配置信息。2.gcc查找/加载头文件的全过程
终端输出:
#include "..." search starts here:
#include <...> search starts here:
/usr/lib/gcc/x86_64-linux-gnu/11/include
/usr/local/include
/usr/include/x86_64-linux-gnu
/usr/include

gcc -I 就是gcc一些新的头文件如果找不到了话用gcc -I 地址既可
前面其实都说到了,-risc_v部分
# 6 "a.c"
int main() {
printf("Hello World!\n" );
printf("Hello RISC-V!\n");
printf("RISC-V");
return 0;
}
执行
echo | gcc -dM -E - | sort > x86_64_macros.txt
echo | riscv64-linux-gnu-gcc -dM -E - | sort > riscv64_macros.txt
diff --color=auto x86_64_macros.txt riscv64_macros.txt
多出了这么一坨:

编译
语法解析与语义分析阶段该阶段对输入文件进行语法解析,将预处理记号转换为语法分析树。在生成语法分析树后,该阶段会执行语义分析,一方面计算表达式的类型,另一方面检查代码的语法合法性。此阶段不仅负责产生大部分编译器警告,还会捕获各类语法解析错误。该阶段的输出产物是抽象语法树(Abstract Syntax Tree,AST)。
!4 = !{i32 7, !"frame-pointer", i32 2} 没了,简单查了下这玩意是方便调试的,等于把它删了后gdb不太方便了
正如前文讲义所讲:volatile(禁止编译器对变量的优化)会被“严格执行”
源代码:
#include <stdio.h>
int main() { // compute 10 + 20
int x = 10, y = 20;
int z = x + y;
printf("z = %d\n", z);
return 0;
}
x86:
.text
.file "b.c"
.globl main # -- Begin function main
.p2align 4, 0x90
.type main,@function
main: # @main
.cfi_startproc
# %bb.0:
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset %rbp, -16
movq %rsp, %rbp
.cfi_def_cfa_register %rbp
subq $16, %rsp
movl $0, -4(%rbp)
movl $10, -8(%rbp)
movl $20, -12(%rbp)
movl -8(%rbp), %eax
addl -12(%rbp), %eax
movl %eax, -16(%rbp)
movl -16(%rbp), %esi
leaq .L.str(%rip), %rdi
movb $0, %al
callq printf@PLT
xorl %eax, %eax
addq $16, %rsp
popq %rbp
.cfi_def_cfa %rsp, 8
retq
.Lfunc_end0:
.size main, .Lfunc_end0-main
.cfi_endproc
# -- End function
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "z = %d\n"
.size .L.str, 8
.ident "Ubuntu clang version 14.0.0-1ubuntu1.1"
.section ".note.GNU-stack","",@progbits
.addrsig
.addrsig_sym printf
risc_v32:
.text
.attribute 4, 16
.attribute 5, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
.file "b.c"
.globl main # -- Begin function main
.p2align 1
.type main,@function
main: # @main
# %bb.0:
addi sp, sp, -48 //开辟栈空间
sd ra, 40(sp) # 8-byte Folded Spill
sd s0, 32(sp) # 8-byte Folded Spill
addi s0, sp, 48
li a0, 0
sd a0, -40(s0) # 8-byte Folded Spill
sw a0, -20(s0)
li a0, 10
sw a0, -24(s0) //从这开始复制相加
li a0, 20
sw a0, -28(s0)
lw a0, -24(s0)
lw a1, -28(s0)
addw a0, a0, a1
sw a0, -32(s0)
lw a1, -32(s0)
.LBB0_1: # Label of block must be emitted
auipc a0, %pcrel_hi(.L.str)
addi a0, a0, %pcrel_lo(.LBB0_1)
call printf@plt // 调用printf
# kill: def $x11 killed $x10
ld a0, -40(s0) # 8-byte Folded Reload
ld ra, 40(sp) # 8-byte Folded Reload
ld s0, 32(sp) # 8-byte Folded Reload
addi sp, sp, 48
ret
.Lfunc_end0:
.size main, .Lfunc_end0-main
# -- End function
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "z = %d\n"
.size .L.str, 8
.ident "Ubuntu clang version 14.0.0-1ubuntu1.1"
.section ".note.GNU-stack","",@progbits
.addrsig
.addrsig_sym printf
优化后:
.text
.attribute 4, 16
.attribute 5, "rv64i2p0_m2p0_a2p0_f2p0_d2p0_c2p0"
.file "b.c"
.globl main # -- Begin function main
.p2align 1
.type main,@function
main: # @main
# %bb.0:
addi sp, sp, -16
sd ra, 8(sp) # 8-byte Folded Spill
.LBB0_1: # Label of block must be emitted
auipc a0, %pcrel_hi(.L.str)
addi a0, a0, %pcrel_lo(.LBB0_1)
li a1, 30 //直接加载立即数结果了
call printf@plt
li a0, 0
ld ra, 8(sp) # 8-byte Folded Reload
addi sp, sp, 16
ret
.Lfunc_end0:
.size main, .Lfunc_end0-main
# -- End function
.type .L.str,@object # @.str
.section .rodata.str1.1,"aMS",@progbits,1
.L.str:
.asciz "z = %d\n"
.size .L.str, 8
.ident "Ubuntu clang version 14.0.0-1ubuntu1.1"
.section ".note.GNU-stack","",@progbits
.addrsig
二进制文件的生成和执行
二进制文件其实可以用od 命令来查看
执行
gcc -c a.c
objdump -d a.o //x86架构实现
riscv-linux-gnu-gcc -c a.c
riscv64-linux-gnu-objdump -d a.o//riscv实现
a.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # f <main+0xf>
f: 48 89 c7 mov %rax,%rdi
12: e8 00 00 00 00 call 17 <main+0x17>
17: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # 1e <main+0x1e>
1e: 48 89 c7 mov %rax,%rdi
21: b8 00 00 00 00 mov $0x0,%eax
26: e8 00 00 00 00 call 2b <main+0x2b>
2b: b8 00 00 00 00 mov $0x0,%eax
30: 5d pop %rbp
31: c3
---------------------------------------------------------------------
a.o: file format elf64-littleriscv
Disassembly of section .text:
0000000000000000 <main>:
0: 1141 addi sp,sp,-16
2: e406 sd ra,8(sp)
4: e022 sd s0,0(sp)
6: 0800 addi s0,sp,16
8: 00000517 auipc a0,0x0
c: 00050513 mv a0,a0
10: 00000097 auipc ra,0x0
14: 000080e7 jalr ra # 10 <main+0x10>
18: 00000517 auipc a0,0x0
1c: 00050513 mv a0,a0
20: 00000097 auipc ra,0x0
24: 000080e7 jalr ra # 20 <main+0x20>
28: 00000517 auipc a0,0x0
2c: 00050513 mv a0,a0
30: 00000097 auipc ra,0x0
34: 000080e7 jalr ra # 30 <main+0x30>
38: 4781 li a5,0
3a: 853e mv a0,a5
3c: 60a2 ld ra,8(sp)
3e: 6402 ld s0,0(sp)
40: 0141 addi sp,sp,16
42: 8082 ret
#include <stdio.h>
int main() {
const long long max_num = 100000000LL;
long long sum = 0LL;
for (long long i = 1; i <= max_num; ++i) {
sum += i;
}
printf("Sum from 1 to %lld is: %lld\n", max_num, sum);
return 0;
}
优化效果惊人
gcc -O0 sum.c -o sum0
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ time ./sum0
Sum from 1 to 100000000 is: 5000000050000000
real 0m0.109s
user 0m0.106s
sys 0m0.003s
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ gcc -O1 sum.c -o sum1
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ time ./sum1
Sum from 1 to 100000000 is: 5000000050000000
real 0m0.029s
user 0m0.027s
sys 0m0.002s
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ gcc -O2 sum.c -o sum2
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ time ./sum2
Sum from 1 to 100000000 is: 5000000050000000
real 0m0.002s
user 0m0.000s
sys 0m0.002s
输入
gdb ./sum0
starti
程序是从_start开始的
第二问
gcc -g sum.c -o sum
gdb ./sum
//设置截断点
b sum:13
r
stepi //到return 0
终端显示:
0x00007ffff7c29d90 in __libc_start_call_main (main=main@entry=0x555555555149 <main>, argc=argc@entry=1, argv=argv@entry=0x7fffffffde68) at ../sysdeps/nptl/libc_start_call_main.h:58
58 ../sysdeps/nptl/libc_start_call_main.h: No such file or directory.
(gdb)
main的返回值会被启动代码(_start/__libc_call_main)接收,然后调用 exit ()/exit_group () 等系统调用来完成最终的收尾工作
手册行为和编码规范

cc -g 4.1.c -o 4.1
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ ./4.1
x =2.y=1
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ clang 4.1.c && ./4.1.c
4.1.c:8:5: warning: multiple unsequenced modifications to 'i' [-Wunsequenced]
f(i++,i++);
^ ~~
1 warning generated.
bash: ./4.1.c: Permission denied
clang 直接警告了,下面关闭下
clang 4.1.c -o 4.1 -Wno-unsequenced
ahu_xj@ahuxj-virtual-machine:~/Desktop/c_test/c_handouts$ ./4.1
x =1.y=2

#include <stdio.h>
int main() {
int a[10] = {0};
printf("a[10] = %d\n", a[10]);
return 0;
}

比较简单,用电路搭建和写代码就是不一样,写代码快多了
#include <stdint.h>
#include <stdio.h>
// 定义硬件状态,uint8_t固定宽度的无符号 8 位整数类型
uint8_t PC = 0;
uint8_t R[4] = {0, 0, 0, 0};
uint8_t M[16] = {
0b10001010, // 0: li r0, 10
0b10010000, // 1: li r1, 0
0b10100000, // 2: li r2, 0
0b10110001, // 3: li r3, 1
0b00010111, // 4: add r1, r1, r3
0b00101001, // 5: add r2, r2, r1
0b11010100, // 6: bner0 r1, 4 (注意:你给的末尾是01,但我修正为0100即地址4)
0b11110111 // 7: bner0 r3, 7 (修正末尾为0111即地址7)
};
void inst_cycle() {
//取指
uint8_t inst = M[PC];
//译码并执行
uint8_t op = (inst >> 6) & 0x3; // 取高2位
int jumped = 0;
//li指令
if (op == 0x2) {
uint8_t imm=inst & 0xf;
uint8_t rd=(inst>>4)&0x03;
R[rd]=imm;
}
else if (op == 0x0) {
uint8_t rd = (inst >> 4) & 0x3;
uint8_t rs1 = (inst >> 2) & 0x3;
uint8_t rs2 = inst & 0x3;
R[rd] = R[rs1] + R[rs2];
}
else if (op == 0x3) {
uint8_t rs = (inst >> 4) & 0x3;
uint8_t addr = inst & 0xF;
if (R[rs] != R[0]) {
PC = addr;
jumped = 1;
}
}
// --- 更新 PC ---
if (!jumped) {
PC++;
}
}
int main() {
printf("sEMU 启动: 运行数列求和程序\n");
printf("--------------------------------\n");
int limit = 200; // 运行步数限制
while (limit-- > 0) {
// 如果 PC 指向最后一条指令且不再跳转,说明进入了预期的终点
if (PC == 7 && R[1] == R[0]) {
break;
}
inst_cycle();
printf("PC:%d | r0(目标):%2d | r1(i):%2d | r2(sum):%2d\n",
PC, R[0], R[1], R[2]);
}
printf("--------------------------------\n");
printf("程序运行结束。\n");
printf("最终结果: sum = %d", R[2]);
return 0;
}
看了半天也没看到./a.out是啥
独立环境:这个semu就是的,他提供了cpu,程序在这个环境里运行,但是不知道对错,必须人为检查
宿主环境:linux中可以调用printf啥的函数。这些功能不是cpu直接完成的而是程序向环境的请求。
强化运行时:给模拟器加入一个接口,让这里独立的semu可以跨越环境区操作原本你无法触及的比如屏幕啥的。当 sISA 程序执行 out 时,sEMU 捕获到这个请求,并将其翻译成 Linux 听得懂的 printf。这个过程就叫作“强化运行时环境”——你通过模拟器代码,给裸机程序提供了它原本不可能拥有的能力。
#include <stdint.h>
#include <stdio.h>
uint8_t PC = 0;
uint8_t R[4] = {0, 0, 0, 0};
uint8_t M[16] = {
0b10001010, // 0: li r0, 10
0b10010000, // 1: li r1, 0
0b10100000, // 2: li r2, 0
0b10110001, // 3: li r3, 1
0b00010111, // 4: add r1, r1, r3
0b00101001, // 5: add r2, r2, r1
0b11010100, // 6: bner0 r1, 4
0b01100000, // 7: out r2
0b11111000 // 8: bner0 r3, 8
};
void inst_cycle() {
uint8_t inst = M[PC];
uint8_t op = (inst >> 6) & 0x3;
int jumped = 0;
switch(op){
case 0x2: {//li
uint8_t imm = inst & 0xf;
uint8_t rd = (inst >> 4) & 0x03;
R[rd] = imm;}
break;
case 0x0:{//add
uint8_t rd = (inst >> 4) & 0x3;
uint8_t rs1 = (inst >> 2) & 0x3;
uint8_t rs2 = inst & 0x3;
R[rd] = R[rs1] + R[rs2];}
break;
case 0x3:{//ber0
uint8_t rs = (inst >> 4) & 0x3;
uint8_t addr = inst & 0xF;
if (R[rs] != R[0]) {
PC = addr;
jumped = 1;
}}
break;
case 0x1:{//out指令
uint8_t rs = (inst >> 4) & 0x3;
// sEMU 借助宿主环境的 printf 实现输出功能
printf("\n>>> [sISA OUT]: Register r%d = %d <<<\n\n", rs, R[rs]);}
break;
}
if (!jumped) PC++;
}
int main() {
printf("sEMU 启动: 运行具有输出功能的数列求和程序\n");
printf("----------------------------------------\n");
int limit = 200;
while ((limit--) > 0) {
// 停机条件:到达死循环指令 (PC=8)
if (PC == 8) {
break;
}
inst_cycle();
// 打印流水线状态
printf("PC:%d | r0:%2d | r1:%2d | r2:%2d\n", PC, R[0], R[1], R[2]);
}
printf("----------------------------------------\n");
printf("程序运行结束。最终结果已通过 OUT 指令输出。\n");
return 0;
}
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// sEMU 状态定义
uint8_t PC = 0;
uint8_t R[4] = {0};
uint8_t M[16] = {
0x90, // 0: li r1, 0
0xA0, // 1: li r2, 0
0xB1, // 2: li r3, 1
0x17, // 3: add r1, r1, r3
0x29, // 4: add r2, r2, r1
0xD3, // 5: bner0 r1, 3 (注意:地址变为3了)
0x60, // 6: out r2
0xF7 // 7: bner0 r3, 7 (死循环结束)
};
void inst_cycle() {
uint8_t inst = M[PC & 0xF];
uint8_t op = (inst >> 6) & 0x3;
bool jumped = false;
switch (op) {
case 0x2: // li
R[(inst >> 4) & 0x3] = inst & 0xF;
break;
case 0x0: // add
R[(inst >> 4) & 0x3] = R[(inst >> 2) & 0x3] + R[inst & 0x3];
break;
case 0x3: // bner0
if (R[(inst >> 4) & 0x3] != R[0]) {
PC = inst & 0xF;
jumped = true;
}
break;
case 0x1: // out
printf("%d\n", R[(inst >> 4) & 0x3]);
break;
}
if (!jumped) PC++;
}
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("Usage: %s <n>\n", argv[0]);
return 1;
}
// --- 运行时环境支持:参数传递 ---
// 将命令行输入的参数转换为整数并存入 R[0]
R[0] = (uint8_t)atoi(argv[1]);
// 运行模拟器
int limit=200;
while ((limit--) > 0) {
if (PC == 7) break;
inst_cycle();
}
return 0;
}
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MEM_SIZE (1 << 20) // 1MB
uint8_t ROM[MEM_SIZE];
uint8_t RAM[MEM_SIZE];
int32_t R[32] = {0};
uint32_t PC = 0;
uint64_t cycle_counter = 0; // 64位计数器
// 符号扩展
int32_t sign_extend(uint32_t imm, int n) {
if ((imm >> (n - 1)) & 1) return (int32_t)(imm | (0xFFFFFFFF << n));
return (int32_t)imm;
}
void inst_cycle() {
// 1. 取指 (从 ROM 读取)
uint32_t inst = (uint32_t)ROM[PC] | (ROM[PC+1] << 8) | (ROM[PC+2] << 16) | (ROM[PC+3] << 24);
uint8_t opcode = inst & 0x7F;
uint8_t rd = (inst >> 7) & 0x1F;
uint8_t funct3 = (inst >> 12) & 0x7;
uint8_t rs1 = (inst >> 15) & 0x1F;
uint8_t rs2 = (inst >> 20) & 0x1F;
uint8_t funct7 = (inst >> 25) & 0x7F;
int jumped = 0;
switch (opcode) {
case 0x13: // ADDI
R[rd] = R[rs1] + sign_extend(inst >> 20, 12);
break;
case 0x33: // ADD
if (funct7 == 0x00) R[rd] = R[rs1] + R[rs2];
break;
case 0x37: // LUI
R[rd] = (inst & 0xFFFFF000);
break;
case 0x67: // JALR
{
uint32_t next_pc = PC + 4;
PC = (R[rs1] + sign_extend(inst >> 20, 12)) & ~1;
R[rd] = next_pc;
jumped = 1;
}
break;
case 0x03: // LW / LBU
{
uint32_t addr = R[rs1] + sign_extend(inst >> 20, 12);
if (addr < MEM_SIZE) {
if (funct3 == 0x2) R[rd] = (int32_t)(RAM[addr] | (RAM[addr+1]<<8) | (RAM[addr+2]<<16) | (RAM[addr+3]<<24));
else if (funct3 == 0x4) R[rd] = RAM[addr];
}
}
break;
case 0x23: // SW / SB
{
int32_t imm = sign_extend(((inst >> 25) << 5) | ((inst >> 7) & 0x1F), 12);
uint32_t addr = R[rs1] + imm;
if (addr < MEM_SIZE) {
if (funct3 == 0x2) {
RAM[addr] = R[rs2] & 0xFF; RAM[addr+1] = (R[rs2] >> 8) & 0xFF;
RAM[addr+2] = (R[rs2] >> 16) & 0xFF; RAM[addr+3] = (R[rs2] >> 24) & 0xFF;
} else if (funct3 == 0x0) RAM[addr] = (uint8_t)(R[rs2] & 0xFF);
}
}
break;
}
R[0] = 0;
if (!jumped) PC += 4;
cycle_counter++; // 周期计数
}
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s <bin_file> <max_cycles>\n", argv[0]);
return 1;
}
// 加载 .bin 文件到 ROM
FILE *fp = fopen(argv[1], "rb");
if (!fp) { perror("Failed to open bin file"); return 1; }
fread(ROM, 1, MEM_SIZE, fp);
rewind(fp);
fread(RAM, 1, MEM_SIZE, fp);
fclose(fp);
uint64_t max_cycles = strtoull(argv[2], NULL, 10);
printf("Simulating %s for %lu cycles...\n", argv[1], max_cycles);
// 执行循环
while (cycle_counter < max_cycles) {
inst_cycle();
}
// 检查结束状态
printf("\n--- Simulation Finished ---\n");
printf("Final PC: 0x%08X\n", PC);
printf("Final a0 (x10): %d (0x%X)\n", R[10], R[10]);
return 0;
}
pc在这三条指令循环满足要求:


#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MEM_SIZE (1 << 20) // 1MB
uint8_t ROM[MEM_SIZE];
uint8_t RAM[MEM_SIZE];
int32_t R[32] = {0};
uint32_t PC = 0;
uint64_t cycle_counter = 0;
int is_halted = 0; //停机标志位
// 符号扩展
int32_t sign_extend(uint32_t imm, int n) {
if ((imm >> (n - 1)) & 1) return (int32_t)(imm | (0xFFFFFFFF << n));
return (int32_t)imm;
}
void inst_cycle() {
// 1. 取指
uint32_t inst = (uint32_t)ROM[PC] | (ROM[PC+1] << 8) | (ROM[PC+2] << 16) | (ROM[PC+3] << 24);
// ebreak:0x00100073
if (inst == 0x00100073) {
is_halted = 1;
return;
}
uint8_t opcode = inst & 0x7F;
uint8_t rd = (inst >> 7) & 0x1F;
uint8_t funct3 = (inst >> 12) & 0x7;
uint8_t rs1 = (inst >> 15) & 0x1F;
uint8_t rs2 = (inst >> 20) & 0x1F;
uint8_t funct7 = (inst >> 25) & 0x7F;
int jumped = 0;
switch (opcode) {
case 0x13: // ADDI
R[rd] = R[rs1] + sign_extend(inst >> 20, 12);
break;
case 0x33: // ADD
if (funct7 == 0x00) R[rd] = R[rs1] + R[rs2];
break;
case 0x37: // LUI
R[rd] = (inst & 0xFFFFF000);
break;
case 0x67: // JALR
{
uint32_t next_pc = PC + 4;
PC = (R[rs1] + sign_extend(inst >> 20, 12)) & ~1;
R[rd] = next_pc;
jumped = 1;
}
break;
case 0x03: // LW / LBU
{
uint32_t addr = R[rs1] + sign_extend(inst >> 20, 12);
if (addr < MEM_SIZE) {
if (funct3 == 0x2) R[rd] = (int32_t)(RAM[addr] | (RAM[addr+1]<<8) | (RAM[addr+2]<<16) | (RAM[addr+3]<<24));
else if (funct3 == 0x4) R[rd] = RAM[addr];
}
}
break;
case 0x23: // SW / SB
{
int32_t imm = sign_extend(((inst >> 25) << 5) | ((inst >> 7) & 0x1F), 12);
uint32_t addr = R[rs1] + imm;
if (addr < MEM_SIZE) {
if (funct3 == 0x2) {
RAM[addr] = R[rs2] & 0xFF; RAM[addr+1] = (R[rs2] >> 8) & 0xFF;
RAM[addr+2] = (R[rs2] >> 16) & 0xFF; RAM[addr+3] = (R[rs2] >> 24) & 0xFF;
} else if (funct3 == 0x0) RAM[addr] = (uint8_t)(R[rs2] & 0xFF);
}
}
break;
default:
break;
}
R[0] = 0;
if (!jumped) PC += 4;
cycle_counter++;
}
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("Usage: %s <bin_file> <max_cycles>\n", argv[0]);
return 1;
}
FILE *fp = fopen(argv[1], "rb");
if (!fp) { perror("Failed to open bin file"); return 1; }
// 加载二进制文件
size_t bytes_read = fread(ROM, 1, MEM_SIZE, fp);
rewind(fp);
fread(RAM, 1, MEM_SIZE, fp);
fclose(fp);
ROM[0x00001218+0]=0x73;
ROM[0x00001218+1]=0x00;
ROM[0x00001218+2]=0x10;
ROM[0x00001218+3]=0x00;
RAM[0x00001218+0]=0x73;
RAM[0x00001218+1]=0x00;
RAM[0x00001218+2]=0x10;
RAM[0x00001218+3]=0x00;
uint64_t max_cycles = strtoull(argv[2], NULL, 10);
printf("Simulating %s (Max Cycles: %lu)...\n", argv[1], max_cycles);
while (cycle_counter < max_cycles && !is_halted) {
inst_cycle();
}
printf("\n--- Simulation Finished ---\n");
if (is_halted) {
printf("Reason: ebreak instruction encountered.\n");
} else {
printf("Reason: Maximum cycles reached.\n");
}
printf("Final PC: 0x%08X\n", PC);
printf("Final a0 (x10): %d (0x%X)\n", R[10], R[10]);
printf("Total Cycles: %lu\n", cycle_counter);
return 0;
}





















浙公网安备 33010602011771号