Advertisement
Guest User

buntu 20.04でQEMUを利用してIDEのEclispeでRISC-VのC言語、アセンブラのプログラムをデバッグする方法

a guest
Dec 26th, 2020
386
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 21.73 KB | None | 0 0
  1. Ubuntu 20.04でC言語、アセンブラのプログラムをQEMUで実行して
  2. IDEのEclipse内でお手軽デバッグできたので方法を書きます
  3. Ubuntu Server 20.04のRaspberry Pi 4でもできます。
  4. ここの例ではUbuntu 20.04のパッケージのgcc RISC-Vクロスコンパイラを使用してるので
  5. RISC-VのRV64GCでABIがilp64dの場合です
  6.  
  7.  
  8. 1.QEMU user modeのインストール
  9.  
  10. sudo apt-get install qemu-user
  11.  
  12.  
  13. 2.gccのRISC-V RV64GC ilp64d linuxのクロスコンパイラをインストール
  14.  
  15. sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu
  16.  
  17.  
  18. 3.GDBのインストール
  19.  
  20. sudo apt-get install gdb-multiarch
  21.  
  22.  
  23. 4.makeのインストール
  24.  
  25. sudo apt-get install make
  26.  
  27.  
  28. 5.Eclipse IDE for C/C++ Developers 2020-12-Rのダウンロード
  29.  
  30. https://www.eclipse.org/downloads/packages/release/2020-12/r/eclipse-ide-cc-developers
  31. wget https://ftp.jaist.ac.jp/pub/eclipse/technology/epp/downloads/release/2020-12/R/eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz
  32.  
  33.  
  34. Ubuntu Server 20.04のRaspberry Pi 4ではaarch64版をダウンロードしてください
  35. https://www.eclipse.org/downloads/packages/release/2020-12/r/eclipse-ide-cc-developers
  36. wget https://ftp.jaist.ac.jp/pub/eclipse/technology/epp/downloads/release/2020-12/R/eclipse-cpp-2020-12-R-linux-gtk-aarch64.tar.gz
  37.  
  38.  
  39. 6.OpenJDK JREのインストール
  40.  
  41. sudo apt install default-jre
  42.  
  43.  
  44. 7.Eclipse IDE for C/C++ Developers 2020-12-Rの解凍
  45.  
  46. sudo tar xf eclipse-cpp-2020-12-R-linux-gtk-x86_64.tar.gz -C /opt
  47.  
  48.  
  49. Ubuntu Server 20.04のRaspberry Pi 4では下記になります
  50. sudo tar xf eclipse-cpp-2020-12-R-linux-gtk-aarch64.tar.gz -C /opt
  51.  
  52.  
  53.  
  54. 8.Eclipse IDE for C/C++ Developers 2020-12-Rの実行ファイルのシンボリックリンクを/usr/local/bin/に作成
  55.  
  56. sudo ln -s /opt/eclipse/eclipse /usr/local/bin/
  57.  
  58.  
  59. 9.Eclipse IDE for C/C++ Developers 2020-12-Rの実行
  60.  
  61. eclipse &
  62.  
  63.  
  64. Eclipse IDE Launcherの画面が開いてworkspaceのディレクトリを聞いてくるので
  65. /home/username/eclipse-workspaceにしてLaunchをクリック(おそらくデフォルトのままでいいはずです)
  66. ここでusernameは自分のユーザ名
  67.  
  68.  
  69.  
  70. 10.プロジェクトの作成
  71.  
  72. File→New→C/C++ Projectを選択
  73. 画面のAllを選択してC Managed Buildを選択してNext
  74. C Project画面が開くので
  75. Project name:にプロジェクト名を入力(ここでは作成例としてriscv_c_test01と入力してください)
  76. 左側のProject TypeでExecutableの中のEmpty Projectを選択
  77. 右側のToolchains:でCross GCCを選択してNext
  78.  
  79. Select Configurations画面が開くので
  80. Debug、Release両方にチェックが付いた状態でNext
  81.  
  82. Cross GCC Command画面が開くので
  83. Cross compiler prefix:にriscv64-linux-gnu-を入力
  84. Cross compiler path:に/bin/riscv64-linux-gnu-gccを入力してFinish
  85.  
  86. Welcomの画面が出たままの場合はWelcomの画面を終了してください
  87.  
  88.  
  89. 11.Cソースコードの作成
  90.  
  91. 画面左側のProject Explorerの画面の中の
  92. 作成したプロジェクト名(ここではriscv_c_test01)を右クリック
  93. ポップアップするメニューからNew→Source Fileをクリック
  94. New Source File画面が開くので
  95. Source folderにプロジェクト名が最初から入ってます(ここではriscv_c_test01)
  96. Source fileにCのソース名を入力(ここでは例としてc_test01.cにしてください)
  97. Template:にDefault C Source templateを選択してFinish
  98.  
  99. ここの最後の方に掲載してあるc_test01.cの内容をコピペして
  100. 保存(メニューのFile→Save)してください
  101.  
  102.  
  103. 12.アセンブラソースコードの作成
  104.  
  105. 画面左側のProject Explorerの画面の中の
  106. 作成したプロジェクト名(ここではriscv_c_test01)を右クリック
  107. ポップアップするメニューからNew→Source Fileをクリック
  108. New Source File画面が開くので
  109. Source folderにプロジェクト名が最初から入ってます(ここではc_test01)
  110. Source fileにアセンブラのソース名を入力(ここではc_test01-asm.S)
  111. アセンブラソースの拡張子は.asmにするか.S(大文字のSにする)
  112. 小文字の.sだと認識されない
  113. Template:に<None>を選択してFinish
  114.  
  115. ここの最後の方に掲載してあるc_test01-asm.Sの内容をコピペして
  116. 保存(メニューのFile→Save)してください
  117.  
  118.  
  119. 13.ライブラリの追加
  120.  
  121. sin関数を使っているのでgccのmathライブラリを登録します
  122.  
  123. 画面左側のProject Explorerの画面の中の
  124. 作成したプロジェクト名(ここではriscv_c_test01)を右クリック
  125. ポップアップするメニューの一番下のPropertiesを選択します
  126. Properties for riscv_c_test01画面が開くので
  127. 画面左側でC/C++ General→Path and Symbolsクリックします
  128. Path and Symbols画面が開くのでConfigurationにDebugを選択します
  129. 画面中央のLibrariesタブをクリック
  130. 右側のAddボタンを押してFile:にmを入力してOK(mathライブラリの名前は"m"1文字だけです)
  131.  
  132. 次に上のConfiguration:をReleaseにして同様にmを追加します
  133.  
  134. 次に上のConfiguration:をDebugに戻してからApply and Closeを押します
  135.  
  136.  
  137. 14.ビルド
  138.  
  139. 画面左側のProject Explorerの中のプロジェクト名(ここではriscv_c_test01)をクリックして選択状態にします
  140. ツールバーの左側端のBuild、Launch in 'Run'modeもしくはLaunch in 'Debug'mode、Stopと
  141. ボタンが3つあるところの右隣のLaunch 'Mode'をDebugにします
  142. メニューのProject→Build Projectを選択します
  143. するとビルドが開始されます
  144.  
  145. ConsoleにBuild Finished. 0 errorsと出ればOKです
  146. エラーがあった場合はソースコードが何か間違っているので修正してください
  147.  
  148.  
  149.  
  150. 15.Debugの準備
  151.  
  152. Ubuntu 20.04のコマンドラインで設定ファイルなどを作成します。
  153.  
  154. ホームディレクトリに.gdbinitを作成
  155. vi ~/.gdbinit
  156.  
  157. 以下~/.gdbinitの内容
  158. set auto-load safe-path ~
  159. set confirm 0
  160. set pagination 0
  161. set architecture riscv:rv64
  162. set sysroot /usr/riscv64-linux-gnu
  163.  
  164.  
  165.  
  166. プロジェクトのディレクトリにqemuを起動するためのスクリプトを作成(debug用)
  167. ここで~/eclipse-workspace/はワークスペースのディレクトリ
  168. ~/eclipse-workspace/riscv_c_test01/はプロジェクトのディレクトリです
  169.  
  170. vi ~/eclipse-workspace/riscv_c_test01/qemu.sh
  171.  
  172. 以下~/eclipse-workspace/riscv_c_test01/qemu.shの内容
  173. #!/bin/bash
  174.  
  175. /bin/qemu-riscv64 -L /usr/riscv64-linux-gnu/ -g 10000 ~/eclipse-workspace/riscv_c_test01/Debug/riscv_c_test01 &
  176.  
  177.  
  178.  
  179.  
  180. 作成したqemu.shに実行許可を与える
  181. chmod u+x ~/eclipse-workspace/riscv_c_test01/qemu.sh
  182.  
  183.  
  184.  
  185.  
  186. プロジェクトのディレクトリにqemuを起動するためのスクリプトを作成(実行用)
  187. ここで~/eclipse-workspace/はワークスペースのディレクトリ
  188. ~/eclipse-workspace/riscv_c_test01/はプロジェクトのディレクトリです
  189.  
  190. vi ~/eclipse-workspace/riscv_c_test01/qemu-run.sh
  191.  
  192. 以下~/eclipse-workspace/riscv_c_test01/qemu-run.shの内容
  193. #!/bin/bash
  194.  
  195. /bin/qemu-riscv64 -L /usr/riscv64-linux-gnu/ ~/eclipse-workspace/riscv_c_test01/Debug/riscv_c_test01 &
  196.  
  197.  
  198.  
  199.  
  200. 作成したqemu.shに実行許可を与える
  201. chmod u+x ~/eclipse-workspace/riscv_c_test01/qemu-run.sh
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208. 16.ビルドしたプログラムの実行
  209.  
  210. この段階でビルドが成功していて、プログラムが正常に動作するなら
  211. ビルドしたプログラムを実行可能です
  212. Ubuntu 20.04のコマンドラインから下記を入力します
  213.  
  214. ~/eclipse-workspace/riscv_c_test01/qemu-run.sh
  215. もしくは
  216. bash ~/eclipse-workspace/riscv_c_test01/qemu-run.sh
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225. 17.Debugの設定
  226. 画面左側のProject Explorerの画面の中の
  227. 作成したプロジェクト名(ここではriscv_c_test01)をクリックして選択状態にします
  228.  
  229. ツールバーの左側端のBuild、Launch in 'Run'modeもしくは、Launch in 'Debug'mode、Stopと
  230. ボタンが3つあるところの右隣のLaunch 'Mode'をDebugにします
  231.  
  232. メニューのRun→Debug Configurationsをクリック
  233. Debug Configurations画面が開きます
  234. 画面左側のGDB Remote Applicationをダブルクリックする
  235. 新しくriscv_c_test01 Debugが作成されて右側の画面に自動的に設定が入力されます
  236. 中段あたりのC/C++ Application:に何も入力されてない場合はビルドに失敗してます
  237. 一度GDB Remote Applicationの中のriscv_c_test01 Debugを
  238. 右クリックしてDeleteをクリックして削除してビルドからやり直してください
  239. きちんとビルドされていればC/C++ Application:にDebug/riscv_c_test01が入っているはずです
  240.  
  241.  
  242. 画面のMainタブの一番下、Using GDB(DSF)Automatic Remote Debugging LauncherのSelect Other...をクリック
  243. Select Prefered Launcher画面が開きます
  244. Use configuration specific settingsをチェック
  245. GDB(DSF) Manual Remote Debugging Launcherを選択してOK
  246.  
  247. DebuggerタブのDebugger OptionsのMainタブのGDB debuggerに/bin/gdb-multiarchを入力
  248. GDB command fileに~/.gdbinit
  249. Non-stop modeのチェックが付いていたら外す
  250. 今度はDebugger OptionsのConnectionタブを開き
  251. Type:にTCP、Host name or IP address:にlocalhost、Port numberに10000を入力
  252. Applyを押します
  253.  
  254. まだDebugは押さずにそのままの状態にしてください。
  255.  
  256.  
  257.  
  258. 18.QEMUを実行
  259. Ubuntu 20.04のコマンドラインから先ほど作成したqemu.shを実行します
  260.  
  261. ~/eclipse-workspace/riscv_c_test01/qemu.sh
  262. もしくは
  263. bash ~/eclipse-workspace/riscv_c_test01/qemu.sh
  264.  
  265. するとqemuが起動して10000ポートの接続待ち状態になります
  266.  
  267.  
  268. Ubuntu 20.04のコマンドラインから下記を入力することでqemu.shが実行中になってるのがわかります
  269.  
  270. ps -ef | grep qemu-riscv64
  271.  
  272.  
  273. /bin/qemu-riscv64 -L /usr/riscv64-linux-gnu/ -g 10000 /home/usershin/eclipse-workspace/riscv_c_test01/Debug/riscv_c_test01
  274. これが起動してればOKです
  275. grep --color=auto qemu-riscv64
  276. これだけだった場合はQEMUが起動してません
  277.  
  278.  
  279.  
  280.  
  281.  
  282. 19.Debugを開始
  283. さきほどのEclipseのDebug Configurationsの画面に戻って、画面内の右下端のDebugボタンを押します
  284.  
  285. Confirm Perspective Switchという画面が開いた場合はSwitchを押します
  286.  
  287. しばらくするとデバッグが始まり、int mainの中の最初の命令が記述されている行で止まります
  288.  
  289.  
  290. この状態でデバッグを行います
  291. プログラムの標準出力はqemu.shを実行したときのコマンドラインに出力されます
  292.  
  293.  
  294. ステップイン F5もしくはRun→Step Into
  295. ステップオーバー F6もしくはRun→Step Over
  296. 実行再開 F8もしくはRun→Resume
  297. カーソル行まで実行 CTRL+RもしくはRun→Run to Line
  298. ブレークポイント ブレークポイントを設定したい行にカーソルを置いてShift+CTRL+bまたはRun→Toggle Breakpoint
  299. ブレークポイントの解除 解除したいブレークポイントの行にカーソルを置いてShift+CTRL+bまたはRun→Toggle Breakpoint
  300. 変数の確認 Window→Show View→Variablesまたは変数名にカーソルを合わせると変数の内容がポップアップする
  301.  
  302.  
  303. アセンブラデバッグ
  304. Window→Show View→Registersでレジスタービューの表示
  305. Window→Show View→Disassemblyで逆アセンブラビューの表示
  306.  
  307. アセンブラレベルで1命令ずつ実行したい場所の直前まで進めます
  308. (アセンブラで書いた関数をアセンブラレベルで1命令ずつデバッグするにはアセンブラで書いた関数の上にカーソルが来たときに
  309. メニューのRun→Instruction Stepping ModeのチェックをつけてInstruction Stepping Modeにしてから
  310. F5もしくはRun→Step Intoで実行していきます)
  311. そこでメニューのRun→Instruction Stepping Modeのチェックをつけると1命令ずつ実行するようになります
  312. Cのソースコードデバッグに戻るときはRun→Instruction Stepping Modeをもう1度選択してInstruction Stepping Modeのチェックを外します
  313.  
  314. インラインアセンブラの場合はインラインアセンブラの直前で止めてから
  315. メニューのRun→Instruction Stepping Modeを選択してInstruction Stepping Modeにして
  316. インラインアセンブラを抜けるときに再度Run→Instruction Stepping Modeを選択してInstruction Stepping Modeから抜けます
  317.  
  318.  
  319.  
  320. プログラムが終了して実行が終わるとQEMUが終了してEclipseのデバッグも終了します
  321.  
  322.  
  323. デバッグ実行時には毎回Ubuntu 20.04のコマンドラインから
  324. ~/eclipse-workspace/riscv_c_test01/qemu.sh
  325. を実行して、
  326. 画面左側のProject Explorerの画面の中の
  327. 作成したプロジェクト名(ここではriscv_c_test01)をクリックして選択状態にして
  328. Launch modeがDebugになってることを確認し(RunになってたらDebugにする)
  329. メニューのRun→Debug Configurationsを開いて
  330. C/C++ Remote Applicationの中のプロジェクト名+Debug
  331. (ここではriscv_c_test01 Debug)が選択された状態で画面右下端のDebugボタンを押します。
  332.  
  333.  
  334.  
  335. ソースコード編集画面に戻るにはツールバーの画面の右端のボタンの右から2番目のC/C++のボタンを押します
  336.  
  337.  
  338. デバッグが開始しない場合はQEMUの動作がおかしくなってるかもしれません
  339. killコマンドでqemu.shのプロセスを強制終了して18.QEMUの実行からやり直してください
  340. killコマンドの使い方はネットで調べてください
  341.  
  342.  
  343.  
  344. テスト用プログラム
  345.  
  346. 以下c_test01.c
  347.  
  348. extern int test_asm_sin01(int start, int end, int step);
  349. int test_asm_sin02(int start, int end, int step);
  350.  
  351. #include <stdio.h>
  352.  
  353. int func_asm_add(int a, int b);
  354. int main(int argc, char *argv[]) {
  355. int a, i, j;
  356. for (j = 1; j <= 3; j++) {
  357. for (i = 1; i <= 3; i++) {
  358. a = func_asm_add(i, j);
  359. printf("%d + %d = %d\n", i, j, a);
  360. }
  361. }
  362. test_asm_sin01(0, 360, 10);
  363. test_asm_sin02(0, 360, 10);
  364.  
  365. return 0;
  366. }
  367.  
  368. void print01(int i, double a) {
  369. printf("sin(%3d) = %.15f", i, a);
  370. printf("\n");
  371. }
  372.  
  373. int func_asm_add(int a, int b){
  374. int ret;
  375. asm volatile (
  376. "sext.w a0, %1\n\t"
  377. "sext.w a1, %2\n\t"
  378. "add %0, a0, a1\n\t"
  379. :"=r"(ret)
  380. :"r"(a), "r"(b)
  381. :"x1", "x10", "x11"
  382. );
  383. return ret;
  384. }
  385.  
  386. int test_asm_sin02(int start, int end, int step) {
  387.  
  388. double pi = 3.141592653589793;
  389. double num01 = 180.0;
  390. double size = 20.0;
  391. int column = 50;
  392. int ret;
  393.  
  394. asm volatile (
  395. // 関数のパラメーターはa0からa7に格納される
  396. // 後でbgeで比較するので64bitに符号拡張する
  397. "sext.w s1, %1\n\t"
  398. "mv s2, %2\n\t"
  399. "mv s3, %3\n\t"
  400.  
  401. "fmv.d.x fa0, %4\n\t"
  402. "fmv.d.x fa1, %5\n\t"
  403. "fdiv.d fs0, fa0, fa1\n\t"
  404.  
  405. "fmv.d.x fs1, %6\n\t"
  406. "mv s4, %7\n\t"
  407.  
  408. "loop01:\n\t"
  409. // s1 > s2なのでs2に1を足した値をbgeで比較する
  410. // addwを実行すると64bitレジスタの上位32bitは符号拡張される
  411. "addw a0, s2, 1\n\t"
  412. // bgeは符号付き64bitで比較する
  413. "bge s1, a0, jump01\n\t"
  414. "fcvt.d.w fa0, s1\n\t"
  415. "fmul.d fa0, fs0, fa0\n\t"
  416.  
  417. // sin関数の呼び出し
  418. "call sin@plt\n\t"
  419. "fmv.d fs2, fa0\n\t"
  420.  
  421. // s5 = (int)(size * sin() + column / 2)
  422. "fmul.d fa0, fs2, fs1\n\t"
  423. "li a0, 2\n\t"
  424. "fcvt.d.w fa1, a0\n\t"
  425. "fcvt.d.w fa2, s4\n\t"
  426. "fdiv.d fa1, fa2, fa1\n\t"
  427. "fadd.d fa0, fa0, fa1\n\t"
  428. "fcvt.w.d s5, fa0\n\t"
  429.  
  430. // if (s5 > column) s5 = column;
  431. "addiw a0, s4, 1\n\t"
  432. "blt s5, a0, jump04\n\t"
  433. "mv s5, s4\n\t"
  434. "jump04:\n\t"
  435. // if (s5 < 0) s5 = 0;
  436. "bge s5, zero, jump05\n\t"
  437. "mv s5, zero\n\t"
  438. "jump05:\n\t"
  439.  
  440. // スペースをs5回分表示
  441. "mv s6, s5\n\t"
  442. "loop02:\n\t"
  443. "addiw s6, s6, -1\n\t"
  444. "blt s6, zero, jump02\n\t"
  445. "li a0, ' '\n\t"
  446. "call putchar@plt\n\t"
  447. "j loop02\n\t"
  448. "jump02:\n\t"
  449. // '*'を表示
  450. "li a0, '*'\n\t"
  451. "call putchar@plt\n\t"
  452.  
  453. // スペースをcolumn-s5回分表示
  454. "subw s6, s4, s5\n\t"
  455. "loop03:\n\t"
  456. "addiw s6, s6, -1\n\t"
  457. "blt s6, zero, jump03\n\t"
  458. "li a0, ' '\n\t"
  459. "call putchar@plt\n\t"
  460. "j loop03\n\t"
  461. "jump03:\n\t"
  462.  
  463. "fmv.d fa0, fs2\n\t"
  464. "mv a0, s1\n\t"
  465. "call print01\n\t"
  466. "addw s1, s1, s3\n\t"
  467. "j loop01\n\t"
  468. "jump01:\n\t"
  469. "mv %0, zero\n\t"
  470. :"=r"(ret)
  471. :"r"(start), "r"(end), "r"(step), "r"(pi), "r"(num01), "r"(size), "r"(column)
  472. :"x1", "x10", "x11", "x12", "x9", "x18", "x19", "x20", "x21", "x22", "f10", "f11", "f12", "f8", "f9", "f18", "memory"
  473. );
  474. return ret;
  475. }
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487. 以下c_test01-asm.S
  488.  
  489. # test_asm_sin01(int start, int end, int step);
  490. .text
  491. .align 1
  492. .globl test_asm_sin01
  493. test_asm_sin01:
  494. # 保存領域確保
  495. # spの値は常に16バイト境界にする
  496. addi sp, sp, -80
  497. # 戻りアドレスを退避
  498. sd ra, (sp)
  499. # 保存レジスタの値を退避
  500. sd s1, 8(sp)
  501. sd s2, 16(sp)
  502. sd s3, 24(sp)
  503. sd s4, 32(sp)
  504. sd s5, 40(sp)
  505. sd s6, 48(sp)
  506. fsd fs0, 56(sp)
  507. fsd fs1, 64(sp)
  508. fsd fs2, 72(sp)
  509.  
  510. # 関数のパラメーターはa0からa7に格納される
  511. # 後でbgeで比較するので64bitに符号拡張する
  512. sext.w s1, a0
  513. mv s2, a1
  514. mv s3, a2
  515. la a0, pi
  516. fld fa0, (a0)
  517. la a0, num01
  518. fld fa1, (a0)
  519. fdiv.d fs0, fa0, fa1
  520. la a0, size
  521. fld fs1, (a0)
  522. la a0, column
  523. lw s4, (a0)
  524. loop01:
  525. # s1 > s2なのでs2に1を足した値をbgeで比較する
  526. # addwを実行すると64bitレジスタの上位32bitは符号拡張される
  527. addw a0, s2, 1
  528. # bgeは符号付き64bitで比較する
  529. bge s1, a0, jump01
  530. fcvt.d.w fa0, s1
  531. fmul.d fa0, fs0, fa0
  532.  
  533. # sin関数の呼び出し
  534. call sin@plt
  535. fmv.d fs2, fa0
  536.  
  537. # s5 = (int)(size * sin() + column / 2)
  538. fmul.d fa0, fs2, fs1
  539. li a0, 2
  540. fcvt.d.w fa1, a0
  541. fcvt.d.w fa2, s4
  542. fdiv.d fa1, fa2, fa1
  543. fadd.d fa0, fa0, fa1
  544. fcvt.w.d s5, fa0
  545.  
  546. # if (s5 > column) s5 = column;
  547. addiw a0, s4, 1
  548. blt s5, a0, jump04
  549. mv s5, s4
  550. jump04:
  551. # if (s5 < 0) s5 = 0;
  552. bge s5, zero, jump05
  553. mv s5, zero
  554. jump05:
  555.  
  556. # スペースをs5回分表示
  557. mv s6, s5
  558. loop02:
  559. addiw s6, s6, -1
  560. blt s6, zero, jump02
  561. li a0, ' '
  562. call putchar@plt
  563. j loop02
  564. jump02:
  565. # '*'を表示
  566. li a0, '*'
  567. call putchar@plt
  568.  
  569. # スペースをcolumn-s5回分表示
  570. subw s6, s4, s5
  571. loop03:
  572. addiw s6, s6, -1
  573. blt s6, zero, jump03
  574. li a0, ' '
  575. call putchar@plt
  576. j loop03
  577. jump03:
  578.  
  579. fmv.d fa0, fs2
  580. mv a0, s1
  581. call print01
  582. addw s1, s1, s3
  583. j loop01
  584. jump01:
  585. # 戻り値を設定
  586. mv a0, zero
  587.  
  588. # 保存レジスタの値を復帰
  589. ld s1, 8(sp)
  590. ld s2, 16(sp)
  591. ld s3, 24(sp)
  592. ld s4, 32(sp)
  593. ld s5, 40(sp)
  594. ld s6, 48(sp)
  595. fld fs0, 56(sp)
  596. fld fs1, 64(sp)
  597. fld fs2, 72(sp)
  598.  
  599. # 戻りアドレスを復帰
  600. ld ra, (sp)
  601.  
  602. # 保存領域開放
  603. addi sp, sp, 80
  604. jr (ra)
  605.  
  606. .data
  607. .align 3
  608. pi: .double 3.141592653589793
  609. num01: .double 180.0
  610. size: .double 20.0
  611. column: .word 50
  612. .end
  613.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement