• 締切済み

アセンブラの初歩

独習アセンブラという本で1+5をするコードが最初のほうに載っています。http://d.hatena.ne.jp/mir/searchdiary?word=*%5BAssembler%5D (ブログにコードを載せている方がいるので、貼ります↑) ブログを書いている方もおっしゃっていますが、これはASCIIコードの演算なので、例えば、5+9+6+3とかいう演算をしようとしても正しい結果が表示されません。5+9+6+3をやって画面に表示させたい場合どういったコードを書けばいいのでしょうか?サンプルを示してもらえるとありがたいです。

  • pr-1
  • お礼率73% (841/1150)

みんなの回答

  • haruh3
  • ベストアンサー率65% (31/47)
回答No.6

サンプルを書いているうちに他の方からも沢山コメントがついていますね。 でも折角書いたので載せておきます。 基本的に数値計算のプログラムを作成する場合、 1. バイナリ(2進数)で計算をして結果を得る. 2. 得られた結果を10進数で表示する. と、計算と表示とを順次分けて処理します。 理解を容易にするために、冗長なプログラムです。 また書いただけでアセンブルしていないのでもしかすると間違いがないとは言えません。(^^;) --- ; 数値計算して dxレジスタに格納 mov dx,5 ; dx=5 add dx,9 ; dx=dx+9 add dx,6 ; dx=dx+6 add dx,3 ; dx=dx+3 ; dxレジスタにある数値を10進数で表示 mov ax,dx mov dx,0 ; dx:axの上位16bitを初期化 mov bx,10000 ; 10000で割る div bx ; ax=商,dx=剰余 call disp_char ; alの値を文字で表示 mov ax,dx mov dx,0 ; dx:axの上位16bitを初期化 mov bx,1000 ; 1000で割る div bx ; ax=商,dx=剰余 call disp_char ; alの値を文字で表示 mov ax,dx mov dx,0 ; dx:axの上位16bitを初期化 mov bx,100 ; 100で割る div bx ; ax=商,dx=剰余 call disp_char ; alの値を文字で表示 mov ax,dx mov dx,0 ; dx:axの上位16bitを初期化 mov bx,10 ; 10で割る div bx ; ax=商,dx=剰余 call disp_char ; alの値を文字で表示 mov al,dl ; 1の位 call disp_char ; alの値を文字で表示 mov ah, 4Ch ; プログラム終了 mov al, 0 int 21h ; DOS call ; alの値を文字で表示するためのサブルーチン disp_char: push ax push dx mov dl,al ; 0-9までの数値 add dl,30h ; + '0' mov ah,02h ; 1文字表示 int 21h ; DOS call pop dx pop ax ret --- このプログラムは例えば100という数値を"00100"と表示します。 これを"100"と表示できるように改造してみてください。 初めて商が0でなくなるまで表示をskipするとできますよ。

pr-1
質問者

お礼

具体例、本当にありがとうございます。 大変助かりました。 じっくりと、読んでいきます。

  • R32C
  • ベストアンサー率39% (115/290)
回答No.5

例示しろということですので、とりあえず、マイコンが違ってもそうたいした問題 じゃないと思っていますのでM16Cで例示しますと以下のとおりです。 stdio.h のprintfを使っていますが、全部アセンブラじゃないと気がすまないという のでしたら、HEWのCのソースもあるので、 -S でコンパイルして、アセンブリ言語にすればよいかと思います。 また、printf相当のC言語のソースで比較的見やすいものとして、 TOPPERS/JSPのjsp\liblary\log_output.c というものがあり、 これを参考にされてもよいかと思います。 ソース (mainプログラム Cで書いて コンパイラ出力を手で直したもの) ------------------------------------------------------------------------------ ;src,distがINTELのものとは右左逆です。 ; .GLB __SB__ .SB __SB__ .FB 0 ;## # FUNCTION addsub .SECTION program,CODE,align .align .glb $addsub $addsub: ADD.W R1,R0 RTS ;## # FUNCTION main .align .glb _main _main: ; enter #02H ;## # C_SRC : value = addsub(5,9); mov.w #0009H,R0 mov.w #0005H,R1 jsr $addsub mov.w R0,R2 ;## # C_SRC : value = addsub(value,6); mov.w #0006H,R0 mov.w R2,R1 ; value jsr $addsub mov.w R0,R2 ; value ;## # C_SRC : value = addsub(value,3); mov.w #0003H,R0 mov.w R2,R1 ; value jsr $addsub mov.w R0,R2 ; value ;## # C_SRC : printf("5+9+6+3 = %d\n",value); push.w R2 ; value push.w #___T0>>16 push.w #(___T0&0FFFFH) jsr _printf add.b #06H,SP ;## # C_SRC : } ; exitd RTS E2: .glb __iob .glb _getc .glb _getchar .glb $putc .glb $putchar .glb _feof .glb _ferror .glb _fgetc .glb $fgets .glb $fputc .glb _fputs .glb _fread .glb _fwrite .glb _gets .glb _puts .glb $ungetc .glb _printf .glb _fprintf .glb _sprintf .glb $vprintf .glb _vfprintf .glb _vsprintf .glb _fscanf .glb _scanf .glb _sscanf .glb _fflush .glb _clearerr .glb _perror .glb $init_dev .glb $speed .glb _init_prn .glb __sget .glb $_sput .glb $_pput .glb __print ;## # Common Objects --- begin --- ;## # Common Objects --- end --- .SECTION rom_FO,ROMDATA ___T0: .byte 35H ; '5' .byte 2bH ; '+' .byte 39H ; '9' .byte 2bH ; '+' .byte 36H ; '6' .byte 2bH ; '+' .byte 33H ; '3' .byte 20H ; ' ' .byte 3dH ; '=' .byte 20H ; ' ' .byte 25H ; '%' .byte 64H ; 'd' .byte 0aH .byte 00H .END ;## Compile End Time Sun Jul 23 18:10:28 2006 出力ログ (HEWシミュレータ出力) ----------------------------------------------------------------------------- 5+9+6+3 = 23

参考URL:
http://japan.renesas.com/fmwk.jsp?cnt=/download_search_results.jsp&fp=/support/downloads/download_results&layerId=1117
pr-1
質問者

お礼

回答ありがとうございます。 -Sは試してみたんです・・・が出てきたものが分けが分からなくて、 ここで質問させてもらいました。 まだまだ分からない事だらけです・・・

  • shiojiri
  • ベストアンサー率43% (84/192)
回答No.4

レジスタALに入っている16進数の値を10進数にして、 100の桁をCLレジスタ、 10の桁をAHレジスタ、 1の桁をALレジスタ、に代入する。 MOV AL,DL //計算結果をALへ MOV CL,00H //CLをクリア LP1: CMP AL,100 JB JP1 //ALが100より小さいとJP1へジャンプ SUB AL,100 INC CL //ALから100引けなくなるまで引いたカウント JMP LP1 JP1: MOV AH,00H //CLをクリア LP2: CMP AL,10 JB JP2 //ALが10より小さいとJP2へジャンプ SUB AL,10 INC AH //ALから100引けなくなるまで引いたカウント JMP LP2 JP2: PUSH AL //INT21Hを実行してレジスタの値が破壊される為スタックへ退避 PUSH AH MOV DL,CL //100の位を表示 ADD DL.30H MOV AH,02H INT 21H POP DL //10の位を表示 ADD DL.30H MOV AH,02H INT 21H POP DL //1の位を表示 ADD DL.30H MOV AH,02H INT 21H この場合答えが23なら”023”と表示されます。

pr-1
質問者

お礼

回答ありがとうございます。 具体例を示してもらえてうれしいです。 ここまでコードが長くなるんですね。 じっくり勉強します。

  • zap35
  • ベストアンサー率44% (1383/3079)
回答No.3

5+9+6+3の答えは10進数なら23ですが、レジスタ上は16進数なので0x17になります。 画面表示は23という10進数で表示したいのであれば、条件判定文などと組み合わせて、0x17から10の位の2と1の位の3を別々のレジスタに取り出す必要があります。そして0x30を加えて0x32、0x33とすればはじめて「23」という文字として表示されることになります。 アセンブリ言語の仕様やシステムルーチンの有無が分からないので、そのサンプルまでは書くことはできないですね。すみません。

pr-1
質問者

お礼

回答ありがとうございます。 大変、参考になりました。 まだまだアセンブリ言語について分からないので、質問の仕方も曖昧になってすみません。

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.2

1+5 は、そのまま計算すればいいです。 一桁の数字を1桁の文字にするために0x30を足します。 1+0x35 をしているのは、それをまとめてやっていることに相当します。 5+9+6+3の場合は、そのまま計算をして、 10進数に変換して、それぞれの桁を0x30して表示していくことになると思います。

pr-1
質問者

お礼

回答ありがとうございます。 考え方を示してもらえて助かります。 ただ、それをやるには、まだまだ勉強が 必要だと感じました・・・

  • ymmasayan
  • ベストアンサー率30% (2593/8599)
回答No.1

> ブログを書いている方もおっしゃっていますが、これはASCIIコードの演算なので、 move dl,1 add dl,5 ここまでは2進数の計算です。 次の add dl,0X30 で2進数をASCIIに変換しています。 このやり方は結果が9までしか通用しません。 5+9+6+3なら move dl,5 add dl,9 add dl,6 add dl,3 のあと(結果の23を)2桁に分けて2と3をとりだし それぞれをadd 0X30でASCIIに変換することになります。 結構面倒くさいですよ。

pr-1
質問者

お礼

回答ありがとうございます。 そうなんです。9までしか通用しないので悩んでいました。 やはり、桁を分けて表示という事ですか。 難しいですね・・・

関連するQ&A

  • X86アセンブラで 16進数を10進数のASCIIコードに変換する方法

    X86アセンブラで16進数から10進数のASCIIコードに変換する方法を模索しております。 例:  0x64(100d) 期待値:0x31 0x30 0x30 ("1","0","0"の3ByteのASCIIデータ) といった内容になります。 論理演算等で求める手法がございましたら、ご教授頂ければ幸いです。

  • アセンブラ初心者です。

    アセンブラ初心者です。 MacOs上のターミナルでgccをつかいアセンブラのソースコードを表示させてみたら .cstring LC0: .ascii "%d \0" .text .globl _main _main: pushl %ebp movl %esp, %ebp pushl %ebx subl $36, %esp call L9 "L00000000001$pb": L9: popl %ebx movl $1, -16(%ebp) jmp L2 L3: movl $1, -12(%ebp) jmp L4 L5: movl -16(%ebp), %eax imull -12(%ebp), %eax movl %eax, 4(%esp) このようになったのですが1つ疑問があります。それはjmp命令のところでjmp L2またはjmp L4とありますがL2とL4のソースコードは表示されていません....。この部分はどうして表示されないのでしょうか?またどのようになっているのでしょうか?教えてください><ちなみにfor文をつかった単純なかけ算のプログラムをCで書きました。

  • プログラミングC#が難しくて困っています。

    プログラミングをしたいと思い、独習C#を使ってプログラミングの勉強中です。 プログラミングは全くの初心者です。 他の入門書でもそうなのかもしれませんが、論理演算子やビット演算子、配列などの内容が書かれていますが、これらが一体何の役に立つのか分からなくて困っています。 読んでいても理解できないです。 本にケチを付けているわけではないです。 おそらく私にプログラミングのセンスがないんだと思います。 また、この本では、コンソールアプリケーションの説明が多いのですが、私はウェブアプリケーションに関心があります。 基礎だと思って読み進めるべきでしょうか? サンプルプログラムも地道に本の真似をして自分で打っていったほうがいいのでしょうか? わからないことがあってGoogleで調べても、理解できないです。 本当に、プログラミングが難しいです。 独習C#のような本は、全て理解する必要があるのでしょうか? 質問が多くなって申し訳ありません。

  • アセンブラのCAP-X COMP-X

    アセンブラのCAP-X COMP-X  いつも回答いただきありがとうございます。 アセンブラのCAP-X COMP-Xと言っても、知っている人は、少ないのでは無いでしょうか?  アセンブラのプログラムを組む機会自体が、減少していると思えるのです。  私が、最初に情報処理試験で触れたのは、このアセンブラと仮想のコンピュータでした。いつか、征服したいテーマでした。  でも、今でも、アセンブラと仮想機械では、もっとも、シンプルで、アセンブラの言語と原理を知るには、もっともふさわしいのでは、無いかと考えているのです。  その後も、アセンブラと仮想の機械は、進展しましたが、知らない者には、いよいよ理解しがたく、近づくことが、できないので、この CAP-X COMP-Xを  まず、理解したいと考えているのです。、  アセンブラを理解できる人には、なじみの無いアセンブラと仮想機械と思いますが、現在知っているアセンブラから、類推して回答していただけるとありがたいです。  今は、Windowsの時代になってCAP-X COMP-Xをシュミレーションできるソフトも無くなりました。頭の中で仮想するばかりです。  一語16ビットの計算機であって、0を含めて256の整数倍の番地から始まる連続した256語を1記録ブロックとして、最少1記憶ブロックから最大256記憶ブロックを実装することができる。N個の記憶ブロックを使用するとき、アクセスできるアドレスは、 0番地から(256*N-1)番地までである。  Nが、256の時、 256*256-1=65536 となって65Kのアドレス空間を持つことになる。 ●Q01. このメモリーの中で、コードとテータの両者を使っていると解釈してもよいのだろうか? ●Q02. もし、メモリーのアドレス空間をコードとデータの両者を混合して使用していると誤ってプログラムしてしまうとコードをデータとして読み込んだり、コードのアドレスに誤って、データを書いてしまい、これが、原因で、コンピューターが、暴走したりする危険性は、あるのでしょうか? ●Q03. この仮想の機械には、OSのような領域は、存在しないのでしょうか? ●Q04. 必要ないのでしょうか?  OSが、必要であるのなら、65Kの全ての領域は、使用できなくなると考えることができるのでしょうか? ●Q05. アセンブラの記号を作って、実行するようにしています。しかし、アセンブラを機械語にアセンブルして、メモリーにロードする必要があるように感じますが、この機械では、 アセンブラを機械語に翻訳するソフトは、どのようにして利用されるのでしょうか? ●Q06. 最初にアセンブラ言語を機械語に変換するアセンブリ言語をメモリーにロードしてから、アセンブラを機械語に変換して、メモリーにロードして、アセンブリ言語をクリアして使用するということになるのでしょうか? ●Q07. これなら、機械語とデータ領域の合計として65Kを使えるということになるのでしょうか?  16ビットの命令語のうちアドレスを指定できるのは、 ADフィールドの アドレスの下位8ビットを指定することになります。  これでは、256通りしか表現できません。  上位8ビットは、 BR(基底レジスターbase register)で定められる。  つまり、BRを変更しないと256通りのアドレスを超えてのアドレスを指定できなくなる。  このBRを変更するのに、 JSR命令(jump to subroutine)が使用される。subroutineに飛ぶのと、記憶ブロックを超えるのとどうして、同じ命令で行われるのか分かりません。 ●Q08. どうしてでしょうか?  昔、ユニバック、マシーンというのがありました。  36ビット、1ワードの機械でした。36ビットの中に命令部分とアドレス部分16ビットの両方を納めなければならないので、アドレス空間には、限度がありました。  16ビットだと限度のアドレス空間は、65Kワードということになります。  これ以上に大きな空間は、アクセスできない。  バイトマシーンのように最初の命令語によって、何バイトでも、アキュームレーターに収納できて大きなアドレス空間にアクセスできるようになっていなかったのです。  大きな容量のプログラムを作るとき、65Kワードでは、収納できない。それで、使用したのは、オーバーレイという手法でした。  プログラムをセグメントに切って、必要に応じて順にプログラムをメモリーに載せ替えるという方法です。しかし、セグメントが大きくなるとこれでは、収まることができないので限度がありました。 ●Q09. オーバレイのやり方は、記憶ブロックのやり方と同様と考えて良いのでしょうか?  初期的な質問で申訳ありません。  また、質問が続くようなことがありましてもよろしく教授方お願いします。 ーーーーーーーーーー CAP-X Computer Application X https://ja.wikipedia.org/wiki/CAP-X CAP-X とは、かつて情報処理技術者試験でのプログラミング能力試験のために使用されていたアセンブリ言語である。後継のCASLに置き換えられ、現在はCASL IIが使われている。 COMP-X の仕様[編集] COMP-X はデータワード長が16ビット、メモリアドレス長も16ビットのコンピュータである。アドレスはバイト単位ではなくワード単位に付与される。ワード中のビットの番号付けは、最上位ビットを 0 番、最下位ビットを 15 番とする。バイト単位の処理という概念がないため、エンディアンも規定されていない。また、COMP-X には入出力の概念が規定されておらず、何らかの手段でメモリ上にプログラムとデータを格納し、実行し、その結果はメモリを読み取ることでわかるようになっている。従って、入出力命令は存在しない。扱う数は整数のみで、2の補数表現を採用している。 レジスタは次の通り。 ーーーーーーーー COMP-X Compuer X https://ja.wikipedia.org/wiki/CAP-X CAP-X とは、かつて情報処理技術者試験でのプログラミング能力試験のために使用されていたアセンブリ言語である。後継のCASLに置き換えられ、現在はCASL IIが使われている。 命令語は全て 1 ワードであり、先頭から順に OP フィールド(4ビット)、GR フィールド(2ビット)、XR フィールド(2ビット)、AD フィールド(8ビット)で構成される。OP フィールドは命令の種類を表すコード(オペコード)であり、COMP-X には 12 種類の命令しかない。GR フィールドでは演算で使用する GR の番号が指定される。また、JC命令では分岐条件の指定に使われる。XR フィールドではアドレス修飾を行う GR の番号が指定され、内容が 0 の場合は GR0 を意味するのではなく、GR によるアドレス修飾をしない。AD フィールドはアドレスの下位8ビットを指定する。 実効アドレスとは命令で使用するメモリアドレスであり、上位8ビットは BR で、下位8ビットは AD フィールドで指定される。XR フィールドが 0 以外の場合、指定された GR の下位8ビットと AD フィールドの値を加算し、結果の下位8ビットを実効アドレスの下位8ビットとする。

  • PICで温度計をつくりたいのですが。アセンブラを教えてください。

    初歩的な質問でもうしわけないのですが、 PIC16F819のPICを買いまして、CMOS温度センサーにオペアンプをかけ PA1につなぎ、A/D変換 PB0~7まで7セグを並列に3つつなぎ。 PA4,6,7から各ポートにトランジスタのBにいれ、Cに+5、Eに7セグのCOMをいれ 3桁の数字を表示させたいのです。 たしか、ダイナミックスキャンというものだと思います。 とりあえず、センサーから入ってきた数値をそのまま表示させたいのですが。 ダイナミックスキャンのアセンブラのプログラムがうまくいきません。 簡単に教えていただきたいのですが。 わかる方お願いします。 ハードは問題はないと思います。

  • このアセンブラの意味を教えて下さい

    アセンブラ初心者です。「はじめて読む486」を読んで勉強しているのですが、いくら調べても分らないのでどうぞ教えて下さい。次の2つのプログラムが分りません。 ------------------------------------------ db 0eah dw offset set_cs_desc2 dw 20h set_cs_desc2: 以下プログラムが続く --------------------------------- セグメント間ジャンプ命令によってCSレジスタに0020hをロードすると本にあるのですが、先ずdb、dwとは何を意味するのでしょうか。単にバイト、ワードを指定しているのでしょうか?そうだとしたらなぜdb、dwと指定しているのか分りません。 また0eah,20hが何を意味しているのか分りません。 出来れば1行ごとに詳しく教えて戴ければ嬉しいです。 また ------------------------------ db 0eah dw offset set_cs_desc3 dw seg set_cs_desc3 set_cs_desc3: move命令などが続く _text ends end ------------------------------------ セグメント間ジャンプ命令によってCSレジスタに_textをロードすると本にはあるのですが、上のプログラムと同様、0eah,db,dwが分りません。 またsegは何を意味するのか分りません。お手数だとは思いますが、これも1行ごとに詳しく解説していただけないでしょうか? そして2つのプログラム共通に分らないのが、なぜこのコードでCSレジスタにロードする事になるのか分りません。 多分意味している事は簡単な事なのだろうと思うのですが、いろいろ調べても全く手がかりがネットや他の本にもなく苦労しています。 初心者なので出来れば簡単な言葉で教えて戴ければ幸いです。 よろしくお願いいたします。

  • C言語とアセンブラ言語による計算プログラミング

    "AB間の距離を求めなさい。" 下の画像において、AC=r1、BC=r2、∠ACB=α°とするとき、AB間の距離dを求めなさい。 上記の問題について困っております。 この問題の解答については、C言語とアセンブラ言語によるプログラミングで考えるようになっており、FPU(MATH COPROCESSOR)を使用し、C言語側で変数や関数宣言、printfなどでの計算結果出力を記述し、アセンブラ言語側で計算するプログラム問題です。 原則として、C言語側で計算してはいけない仕様になっています。 そして、2つのオブジェクトファイルをリンクさせ、実行可能ファイル(.exe)を作成し、コマンドプロンプト に計算結果を表示する。とういう問題です。 ・アセンブラ言語側での使用する命令のプロセッサアーキテクチャのタイプは「.386」 ・作成するオブジェクトのメモリモデルは、Windowsなので「FLAT」 図の画像は添付してあるので、どうかご回答のほどよろしくお願い致します。

  • 論理和演算子を使って、三項演算子のような簡易分岐ができるようなコードを

    論理和演算子を使って、三項演算子のような簡易分岐ができるようなコードを書けるという テクニックがあるというのを本で読んで試して見たのですが、うまくいきません。 本に書いてあるコードはこんな感じです。 bがなければ、cのプロパティであるdを、それもなければ、500をaに代入する。 bを削除するとdが代入されると思ったのですが、エラーになってしまいます。 //var b = 1; var c = new Object(); c.d = 2; var a = b || c.d || 500 ; どうやったらうまくいきますでしょうか?よろしくお願いします。

  • if文の中で否定演算子を使うことについて

    PHPの勉強をしています。 今、基礎的な内容の本とより実践的な内容の本、コードサンプルが満載の本の 計3冊で勉強しておるのですが、 たまたまなのかわかりませんが、この三冊の中ででてくるコードを見てみると、 if文の中に否定演算子、例えば IF(!A || !B) {   A、もしくはBがfalse だったのが反転してTrueになった場合の処理 }else {   A、Bどちらともtrueだったのが反転してfalseになった場合の処理 } といった条件文に否定演算子を含めたコードサンプルがほとんどです。 。。。。三冊ともこの調子なので もしかしてPHPのコーティング作法なのかな?と思いましたが ネットで検索してもそれらしい情報は見当たらず...... 自分が何がわからないのか それ自体よくわかってないのかもしれませんが IF文を使う際、条件に否定演算子を使うべきときってのがあるんだと思います。 となると、その時を判断する基準などがあるのでしょうか? 初心者なのでなにか重大な思い違いをしてるのではないかと思ってます。 なにか気づくことがあれば教えてください。

    • ベストアンサー
    • PHP
  • CalendarViewを使ってカレンダー作成

    Javaの知識はある程度学んでandroidのアプリを作りたいと思い、カレンダーを作りたいのですが、 http://d.hatena.ne.jp/Kazzz/searchdiary?word=%2A%5BCalendarView%5D さんのCalendarViewを使えば楽に作れるとの情報を得たのですがどこにどのように記述していけばいいかわからず困っています。 予定を追加、確認などできるスケジュール機能(SQLite?)をとりあえず作っていきたいです。 (できれば今後googleカレンダーと同期できるように) コード又は参考になるサイトでもあれば教えていただきたいです

専門家に質問してみよう