N88-BASIC、アセンブラ、Cでポインター (6回目)
2023/1/31(火)
N88-BASIC、アセンブラ、Cでポインター (6回目)
C言語にポインターが存在する意味が
文字列中のアルファベットの小文字を
大文字に変換するプログラムを作ることで
何となく分かるようにするシリーズです
今回はアセンブラ(8086系)の
プログラムの紹介です
前回のポインターを使用したCからの変換です
プログラムと解説はコメント(/* … */)を見て下さい
blg~.zip中のptr006asm.cです
#include <stdio.h> /* printf等使用の為 */
void main(void) /* mainから実行 */
{
char* p; /* p = a (aは&a[0]) */
char a[256]; /* 255文字+終端'\0' */
printf("? ");
gets_s(a, 256); /* 文字列入力 */
printf("%s\n", a); /* 文字列表示 */
p = a; /* mov ebx,aがerrorの為 */
__asm /* 次の{}内がアセンブラ */
{
mov ebx,p; ; ebxレジスタ(32bit) = p
L1:
mov al,[ebx] ; alレジスタ(8bit) = *ebx
test al,al ; al & al (0のチェック)
je L3 ; if (al == 0 ) goto L3
cmp al,'a' ; if (al < 'a') goto L2
jl L2
cmp al,'z' ; if (al > 'z') goto L2
jg L2
sub al,'a'-'A' ; al -= 'a' - 'A'
mov [ebx],al ; *ebx = al
L2:
inc ebx ; ebx++ (ebx = ebx + 1)
jmp L1 ; goto L1
L3:
}
printf("%s\n", a); /* 文字列表示 */
gets_s(a, 256); /* キー入力待ち */
}
gets_s(a, 256);
がエラーとなる場合は(多少動作は異なりますが)
scanf_s("%s", a, 256);
を使用して下さい
アセンブラのコメント(;以降)
にC風の説明を書いておきましたので
前回と比べれば分かると思います
AL:8bits、AX:16bits、EAX:32bitsレジスター
ですが、EAXは8086では使用できないので
80386以降位?で使用して下さい
Windows 10以降が動いていれば問題ないと
思います
また、アドレスを32bitsで扱っているため
Cコンパイラーは32bitsモードでコンパイル
して下さい
C、インラインアセンブラは、
Cコンパイラーなどを準備しておいて下さい
例、Microsoft Visual Studioなど
windowsのconsoleアプリは実行終了後
ウインドウが閉じてしまうので
最後にキー入力待ちを入れています
使用している入力関数は
Microsoft Visual Studio以外では
代替え関数に変更する必要があるかも
しれませんがご了承下さい
余談
6809アセンブラには関節アドレッシング
(C言語のポインターへのポインター)があり
アドレスの内容がアドレスとしてアクセスする
事ができました
ですのでアセンブラが分かる方にとって
C言語のポインターは簡単だと思います
blg~.zip(ptr006asm.c)は
以下のリンクからダウンロードできます
N88-BASIC、アセンブラ、Cでポインター (6回目)
C言語にポインターが存在する意味が
文字列中のアルファベットの小文字を
大文字に変換するプログラムを作ることで
何となく分かるようにするシリーズです
今回はアセンブラ(8086系)の
プログラムの紹介です
前回のポインターを使用したCからの変換です
プログラムと解説はコメント(/* … */)を見て下さい
blg~.zip中のptr006asm.cです
#include <stdio.h> /* printf等使用の為 */
void main(void) /* mainから実行 */
{
char* p; /* p = a (aは&a[0]) */
char a[256]; /* 255文字+終端'\0' */
printf("? ");
gets_s(a, 256); /* 文字列入力 */
printf("%s\n", a); /* 文字列表示 */
p = a; /* mov ebx,aがerrorの為 */
__asm /* 次の{}内がアセンブラ */
{
mov ebx,p; ; ebxレジスタ(32bit) = p
L1:
mov al,[ebx] ; alレジスタ(8bit) = *ebx
test al,al ; al & al (0のチェック)
je L3 ; if (al == 0 ) goto L3
cmp al,'a' ; if (al < 'a') goto L2
jl L2
cmp al,'z' ; if (al > 'z') goto L2
jg L2
sub al,'a'-'A' ; al -= 'a' - 'A'
mov [ebx],al ; *ebx = al
L2:
inc ebx ; ebx++ (ebx = ebx + 1)
jmp L1 ; goto L1
L3:
}
printf("%s\n", a); /* 文字列表示 */
gets_s(a, 256); /* キー入力待ち */
}
gets_s(a, 256);
がエラーとなる場合は(多少動作は異なりますが)
scanf_s("%s", a, 256);
を使用して下さい
アセンブラのコメント(;以降)
にC風の説明を書いておきましたので
前回と比べれば分かると思います
AL:8bits、AX:16bits、EAX:32bitsレジスター
ですが、EAXは8086では使用できないので
80386以降位?で使用して下さい
Windows 10以降が動いていれば問題ないと
思います
また、アドレスを32bitsで扱っているため
Cコンパイラーは32bitsモードでコンパイル
して下さい
C、インラインアセンブラは、
Cコンパイラーなどを準備しておいて下さい
例、Microsoft Visual Studioなど
windowsのconsoleアプリは実行終了後
ウインドウが閉じてしまうので
最後にキー入力待ちを入れています
使用している入力関数は
Microsoft Visual Studio以外では
代替え関数に変更する必要があるかも
しれませんがご了承下さい
余談
6809アセンブラには関節アドレッシング
(C言語のポインターへのポインター)があり
アドレスの内容がアドレスとしてアクセスする
事ができました
ですのでアセンブラが分かる方にとって
C言語のポインターは簡単だと思います
blg~.zip(ptr006asm.c)は
以下のリンクからダウンロードできます