No.5ベストアンサー
- 回答日時:
全部面倒見ないとイケナイかな。
字数の関係があるから、答えを全ては書けません。
よって、今回は考え方のみ記述しますね。
(1)初期処理
・セグメントレジスタの設定(既にやっている)
・初期メッセージの表示
(2)中核処理
これは^Cを入力すれば止まるのだから、
無限ループで良いでしょう。以下のことをします。
(a)数値1の入力を促すメッセージを表示する
(b)数値1を入力する
(c)入力値をチェックする
エラー時はメッセージを表示して(a)に戻る
(d)演算子(+か-)を入力する
上記以外はメッセージを表示して(a)に戻る
(e)数値2の入力を促すメッセージを表示する
(f)数値2を入力する
(g)入力値をチェックする
エラー時はメッセージを表示して(d)に戻る
(h)数値1と数値2を(d)に基づいて加減算する
(i)結果を編集し、表示を行う
観念的なコード
CALL 初期処理
MUGEN: ;ここから(2)
CALL 数値1入力
JC MUGEN ;エラー時は戻る
CALL 演算子入力
JC MUGEN ;エラー時は戻る
CALL 数値2入力
JC MUGEN ;エラー時は戻る
CALL 演算
CALL 結果編集
CALL 表示処理
JMP MUGEN ;戻る
疑問点の指摘
(1)復帰改行
0Ah,0Dh とあるが、普通は0Dh,0Ah 文字通り、
復帰(0Dh)、改行(0Ah)の順に書く。後退法の
心配をしたと思うが、DW擬似命令の場合話で、
DB擬似命令では書いた順にメモリに格納される。
(2)セグメントレジスタの設定
mov ax,Data → mov ax,SEG IN_BUF
20年くらい前にやってたことなんで自信ないが、
こう書くような気がする。それと、COM(TINY)
形式の場合はDSの設定は不要です。
おまじないで入れときましょうか。
(3)OUT_DATA_0など
バッファド入出力(機能コード:10)を使えば、
入力値の再表示は不要なので、OUT_DATA_0 等は
不要です。ちょっと工夫が要るけどね。
(4)結果表示領域
結果が何ケタになるのか分からないのに、領域が
1バイト分しかない。
※ラベルと擬似命令、命令とオペランドの間に空白が
ありません。
No.4
- 回答日時:
#3です。
いきなり間違ってた。
最後のMOVが間違い
誤:MOV DI,DX
正:MOV DX,DI
この回答への補足
一応、途中まで組んでみました。
;-----------------------------
;筆算的加減算
;-----------------------------
Codesegment
Codeends
Datasegment
Dataends
Stacksegment stack
Stackends
;-----------------------------
;Data Segment
;-----------------------------
Datasegment
IN_BUFdb4
db0
db3 dup(0)
db0
VALUE_0dw0;入力した値1
VALUE_1dw0;入力した値2
RESULTdw0;結果
EXPRESSIONdb'';式
TENdw10
OUT_BUFdb0Ah,0Dh;改行
OUT_DATA_0db'';入力した値1を出力
db0Ah,0Dh;改行
OUT_EXPRESSIONdb'';式
OUT_DATA_1db'';入力した値2を出力
db0Ah,0Dh;改行
db'------',0Ah,0Dh;筆算の線と改行
OUT_CODEdb'';符号
OUT_RESULTdb'';計算結果
db0Ah,0Dh,'$';改行と終了
MSG_0db'アセンブリ 筆算的出力プログラム',0Ah,0Dh,'$'
MSG_1db'1つめの値を入力してください==>','$'
MSG_2db0Ah,0Dh
db'+か-を入力してください','$'
0Ah,0Dh
MSG_3db'2つめの値を入力してください==>','$'
MSG_Edb0Ah,0Dh,'エラー発生!もう一度やり直してください。'
Dataends
;-----------------------------
;Stack Segment
;-----------------------------
Stacksegment stack
dw100hdup(?)
Stackends
;-----------------------------
;Code Segment
;-----------------------------
Codesegment
assumecs:Code,ds:Data,ss:Stack
;-----------------------------
;Program MAIN start
;-----------------------------
Mainprocnear
movax,Data;set DATA segment
movds,ax
;-----------------------------メッセージ出力
movah,09h
movdx,offset MSG_0
int21h
movah,09h
movdx,offset MSG_3;2つめの値
int21h
;-----------------------------値1の入力
movah,09h
movdx,offset MSG_1
int21h
こんな感じなんですけど、続きをどうすればよいか、教えてもらえませんか・・?
No.3
- 回答日時:
DOS上での話と仮定します。
(1)文字列の入力
文字数の上限を指定して、エコーバックやバックスペースも行う
0Ahという機能コードを使います。
X DB 5 ;入力文字数(符号、数字3桁、リターンを含む)
N DB ? ;実際に入力されたバイト数が返る領域
D DB 5 DUP (?) ;入力領域
MOV AH,0Ah
MOV DX,OFFSET X
INT 21h
(2)入力チェックと数値変換
AXに変換値が入る。Cy=0:正常/Cy=1:エラー
CONV:
MOV BX,1 ;BH←0、BL←1
MOV SI,OFFSET N ;実入力バイト数のアドレス
CLD ;デクリメントフラグクリア
LODSB ;AL←[SI++]=実入力バイト数
CBW ;符号拡張(AH←0)
CDW ;符号拡張(DX←0)
XCHG AX,CX ;CX←実入力バイト数
JCXZ C4 ;CX=0(未入力)なら出口へ分岐
C1:
LODSB ;AL←[SI++]
CMP AL,'+'
JE C2 ;"+"であればC2へ分岐
CMP AL,'-'
JNE C3 ;"-"でなければC3へ分岐
C2:
OR BH,BH ;最初かどうか調べる
JNZ C4 ;最初でなければ出口へ分岐
C3:
SUB AL,'0' ;文字コードを減じて数値化する
JB C4 ;0未満なら出口へ分岐
CMP AL,9 ;9と比較
JA C4 ;9より大きければ出口へ分岐
CBW ;符号拡張(AH←0)
XCHG AX,DI ;数値をDIに退避
MOV AX,10 ;10倍するための定数
MUL DX ;既存の値を10倍
ADD AX,DI ;先程の数値を加算
MOV DX,AX ;DXに変換値を記録
OR BH,1 ;文字が検査済みであることを記録
LOOP C1 ;--CX !=0 ならC1へ分岐
DEC BX ;BL←0(ここまで来れば正常)
CMP BH,'-' ;ハイフンがあったか調べる
JNZ C4 ;ハイフンが無ければ出口へ分岐
NEG AX ;マイナスにする
C4:
SHR BL,1 ;BLを右シフトしてCyへ結果を反映させる
RET
(3)数値表示
AXに数値があるとする
B DB 5 DUP (?) ;文字格納領域
DB 0Dh,0Ah,'$' ;復帰、改行、終端記号
DISP:
MOV DI,OFFSET B[5];ポインタを初期化
XOR CX,CX ;CX←0 符号
MOV BL,10 ;定数
OR AX,AX ;マイナスかどうか調べる
JGE D1
INC CX ;マイナスを記録
NEG AX
D1:
CBW ;符号拡張
DIV BL ;AXをBLで除算
XCHG AL,AH ;商と剰余を入れ替える
ADD AL,'0' ;文字コード化する
DEC DI ;ポインタを更新する
MOV [DI],AL ;格納する
XCHG AL,AH ;商と剰余を入れ替える
OR AL,AL ;0かどうかを調べる
JNZ D1 ;ゼロでなければ続ける
JCXZ D2;CX=0なら分岐
DEC DI ;ポインタを更新する
MOV [DI],BYTE PTR '-' ;符号を格納する
D2:
MOV AH,09h ;機能コード
MOV DI,DX ;データ領域
INT 21h
RET
途中、レジスタの使い方とか、突っ込まれても
大丈夫なように、よく噛み砕いて使ってください。
あと、デバッグしてないから間違ってたらゴメン
No.2
- 回答日時:
プログラムを組む上でのアドバイスではなくて恐縮ですが質問をする上でのアドバイスを
質問するときは環境を具体的に書かれたほうがいいです
アセンブラの種類やパソコンのOSなどできるだけ細かいほうがいいですね
プログラムの仕様ももっと詳しい方が回答も得られやすいです
実際の入力と出力の例も書いたほうがいいです
あと一番いいのは自分が書いたコードをコピーしてアドバイスを求めることですね
No.1
- 回答日時:
別に普通に加算命令(ADD,ADC)と減算命令(SUB,SBB)を使えば良いだけじゃないですか?
レジスタは16bitなので3桁の整数など余裕で扱えるし、他に二進化十進数やアンパック十進数で計算する方法もあります、その為の命令もありますしね。
それよりも入力や出力で数値を変換する部分が大変ですね。
普通はBIOSやAPIなどで入出力の仕様が定義されていて、それに合わせて変換するサブルーチンを作って呼び出しますね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 3 2022/10/04 15:07
- Java javaの質問です 次の機能を有するメソッド4つを自クラスに作成し、実装したいです 【機能】 足し算 1 2022/06/15 17:49
- C言語・C++・C# このプログラミングの問題を教えてほしいです。 キーボードからデータ数nとn個のデータを入力し、平均値 3 2022/12/19 22:51
- C言語・C++・C# このプログラミングの問題を教えて欲しいです。 キーボードから整数kを入力し、kが配列aの中に何個存在 2 2022/12/19 22:50
- Java java 飾子を付けること(public static・・・) ・コンソールへの出力処理はmainメ 2 2022/06/16 19:34
- システム CPUの問題について 2 2022/07/09 12:04
- C言語・C++・C# 至急教えてください!プログラミングの問題です。 正の整数nを入力させると、1からnまでの整数を出力し 9 2022/07/16 23:45
- Java java 入力された文字列を数値に置き換えて整数にし、計算をしたいです。 <を10として /を1とし 4 2022/05/16 21:08
- その他(コンピューター・テクノロジー) 量子コンピュータの動作原理がわかりません。同じビットが、1でも0でも有って良いだろうか? 3 2023/02/04 03:20
- C言語・C++・C# 【CASLプログラム】 定数(80と55)を確保し、その和をGR1に、その差をGR2に求めるCASL 1 2022/12/16 01:17
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
*をユーザーが入力した数字の数...
-
正負を反転させて出力するプロ...
-
scanfが2回使えない・・・?;
-
数字以外が入力されたらエラー...
-
プログラミング初心者です。 Py...
-
java初心者です。入力されたの...
-
"scanf"でエンターで改行させな...
-
if文の条件にscanf関数を使うと…?
-
2進数の1の数を数える問題
-
cout関数を使っているのですが...
-
プログラミングの問題で、キー...
-
プログラミングの問題です 「金...
-
scanf が無視されます
-
scanf関数について
-
C言語 逆ピラミッドの作り方
-
scanf("%s", buf);でスペースを...
-
Eclipseコンソール表示を、リセ...
-
VBでの日付入力値のフォーマッ...
-
enterでループ終了
-
UWSCで変数をキー入力
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
double型が正常に認識されてい...
-
プログラミング初心者です。 Py...
-
正負を反転させて出力するプロ...
-
Excel VBAで、Application.Inpu...
-
C言語について。
-
batプログラム上で文字列を入力...
-
*をユーザーが入力した数字の数...
-
cout関数を使っているのですが...
-
漢字のソートについて
-
数字以外が入力されたらエラー...
-
Userformの入力順序をタブオー...
-
ワードで文字を入力する時の変...
-
Linuxで入力待ちなしkeyread関...
-
java初心者です。入力されたの...
-
EDITコントロールで入力できる...
-
Eclipseコンソール表示を、リセ...
-
小数か整数かを判定する方法
-
C言語scanf_sで何故か2回入力に...
-
VB.NETで16進数+16進数や16進...
-
Linuxプログラミングで、キーボ...
おすすめ情報