「アセンブリ言語」 - 読書ノート - 第 7 章 - メモリ アドレスを見つけるためのより柔軟な方法

7.1 and および or の指示

  1. and 命令: 論理 AND 命令、ビットごとの AND 演算
mov al, 00001111b
and al, 01010101b
;结果: 00000101b  双方都为1的位为1,其他为0
  1. or 命令: 論理 or 命令、ビットごとの or 演算
mov al, 00001111b
and al, 01010101b
;结果: 01011111b  只要有1方为1的位就为1,双方都是0的位为0

7.2 ASCIIコードについて

コンピュータはそれを認識するだけです01
そのため、人々は多くのルールを定義しています。ASCIIつまり、テキストのエンコード ルール
(小文字など) は、aでのASCIIエンコードを定義します97
したがって、a読み取りと書き込みのプロセスは次のようになります。

  • 書く
    1. キーボードを押すa
    2. プログラムはルールaに従ってASCIIコーディングされたものを受け取り、97
    3. 97バイナリに変換して1100001保存します。(メモリまたはハードディスク)
  • 読む
    1. 1100001プログラムは、コンピュータがこれが 10 進数であることを認識するまでメモリから読み取ります。97
    2. ルールを使用したデコードASCII97小文字の表現a
    3. 描画されることをグラフィックス カードに通知しますa(先ほど紹介したのはビデオメモリの書き込み、描き方は表示の作業です)

データ自体は無効であり、プログラムが特定のルールに従ってデータを処理する場合にのみ意味があることがわかります。
別のルール セットを含む別のプログラムがある場合、それが読み取られると、その内容は1100001まったく異なる意味になります。

7.3 文字形式で与えられるデータ

アセンブリプログラムでは、'......'文字データは(シングルクォーテーション)の形式で宣言され、コンパイラによって対応するASCIIコードに変換されます。

手順7.1

assume cs:code, ds:data

data segment	;16字节
	db 'Jerry'	; 4A 65 72 72 97
	db 'abc'	; 61 62 63
data ends

code segment
start:	mov al, 'a'
		mov bl, 'b'
		
		mov ax, 4c00h		
		int 21h
code ends
end start

ここに画像の説明を挿入
コンパイラは文字をASCIIコードに変換します。

7.4 大文字と小文字の変換に関する問題

ここに画像の説明を挿入

  1. コード表を確認してくださいASCII(ただし、ルールは順守できます)。ASCII大文字と小文字のコードは関連しています32
  2. 大文字を小文字に変換する場合は、大文字を小文字の +32、小文字を大文字の -32 に変換します。(しかし、ASCIIデザインは非常に賢いので、現在の大文字を判断する必要はありません)
  3. Aとの違いはa1位です600100000b= 20H= 32
    01 0 00001
    01 1 00001

ビット演算を使用してand 1101 1111大文字に変換します。(6 番目の位置は 0、他のビットは変更されません)

	  A:01000001  a:01100001
and	20H:11011111	11011111
-----------------------------
	  A:01000001  A:01000001

ビット演算を使用して or 0010 0000小文字に変換します。(ビット 6 は 1、他のビットは変更されません)

	  A:01000001  a:01100001
or	20H:00100000	00100000
-----------------------------
	  a:01100001  a:01100001

ここに画像の説明を挿入

7.5 [bx+idata] (変数 + 固定オフセット)

idata:定数を示します。データがメモリからフェッチされ、メモリに送信される
mov ax, [bx+200]ことを示します最終的な結果は物理アドレス: content + constantであり、物理アドレスを取得した後、アドレスからコンテンツが取り出されます。((ds)*16+(bx)+200)ax
[]bx200

質問7.1

以下のプログラムを実行後、ax、bx、cxの内容をメモします。

code segment				; ax	bx		cx		ds
start:	mov ax, 2000h		; 2000
		mov ds, ax          ; 						2000
		mov bx, 1000h       ;		1000
		mov ax, [bx]        ; 00BE
		mov cx, [bx+1]      ; 				0600			
		add cx, [bx+2]      ;				0606
code ends                   
end start

ここに画像の説明を挿入

7.6 [bx+idata] を使用して配列を処理する

idata: アドレスの受け渡しの理解によれば、idata は配列アドレスに相当します
bx。 : 配列を走査するときの i に相当する走査量を示します。

データで定義されている最初の文字列を大文字に変換し、2 番目の文字列を小文字に変換します。

assume cs:code;, ds:data

data segment	;16字节
	db 'jerry'
	db 'ABCDE'
data ends

code segment			
start:	mov ax, data	
		mov ds, ax  
		
		mov bx, 0			; i = 0		
		mov cx, 5			; len = 5
	s:	mov al, [0+bx]		; 0表示第一个数组的位置 bx表示索引
		and al, 11011111b	; 转大写
		mov [0+bx], al		; 送回内存
		
		mov al, [5+bx]		; 5表示第二个数组的位置 bx表示索引
		or  al, 00100000b	; 转小写
		mov [5+bx], al		; 送回内存
		
		inc bx				; i++
		loop s				; cx--; cx != 0 继续循环,循环结束
		
		mov ax, 4c00h
		int 21h
code ends                   
end start

ここに画像の説明を挿入

7.7 SI と DI (送信元アドレス > 宛先アドレス)

siおよび はdi8086CPU の同様の機能を持つbxレジスタです。
si と di を 2 つの 8 ビットレジスタに分割して使用することはできません。

  • 一般的な使用法は、2 つのメモリ間でデータをコピーする場合です。
    ds:si はソースを指します
    ds:diは宛先を指します

質問7.2

siと を使用して、文字列をその後ろのデータ領域にコピーしますdiwelcome to masm!!

assume cs:codesg,ds:datasg
datasg segment
	db 'welcome to masm!'	;16字节
	db '................'	;16字节
datasg ends

codesg segment			
start:	mov ax, datasg	
		mov ds, ax
		mov si, 0			; 指向第一行字符开头
		mov di, 16			; 指向第二行字符开头
		
		mov bx, 0			; i = 0	对应字符索引	
		mov cx, 8			; len = 8 每次复制一个字,共循环处理8次
	s:	mov ax, [si+bx]		; 取第一行的第bx个字符
		mov[di+bx], ax		; 送到第二行的第bx位
		add bx, 2			; i++ (每次偏移1个字 = 2字节)
		loop s				; cx--; cx != 0 继续循环,循环结束
		
		mov ax, 4c00h
		int 21h
codesg ends                   
end start

ここに画像の説明を挿入

質問7.3

最適化問題 7.2 コード量を削減します。OR またはORを使用して削減
できます。[bx+idata][si+idata][di+idata]

assume cs:codesg,ds:datasg
datasg segment
	db 'welcome to masm!'	;16字节
	db '................'	;16字节
datasg ends

codesg segment			
start:	mov ax, datasg	
		mov ds, ax
		mov si, 0			; i = 0
		mov cx, 8			; len = 8 每次复制一个字,共循环处理8次
	s:	mov ax, 0[si]		; 取第一行(偏移量0)的第bx个字符
		mov 16[si], ax		; 送到第二行(偏移量16)的第bx位
		add si, 2			; i++ (每次偏移1个字 = 2字节)
		loop s				; cx--; cx != 0 继续循环,循环结束
		
		mov ax, 4c00h
		int 21h
codesg ends                   
end start

ここに画像の説明を挿入

7.8 [bx+si]和[bx+di]

bx+ 変数、より柔軟
たとえば、配列演算:
si: 元の配列を示します (メモリ内の配列の最初の要素のアドレスを指します)
di: ターゲット配列を示します (配列の最初の要素のアドレスを指します) bx:インデックス
を示します。1
サイクルで 2 つの配列を操作すると便利です。

質問7.4

以下のプログラムを実行後、ax、bx、cxの内容をメモします。

; 2000:1000 BE 00 06 00 00 00
assume cs:codesg
codesg segment			    ; ax	bx		cx		ds		si		di
start:	mov ax, 2000H	    ; 
		mov ds, ax          ; 						2000
		mov bx, 1000H		; 		1000
		mov si, 0		    ; 								0000
		mov ax, [bx+si]		; 00BE
		inc si				;								0001
		mov cx, [bx+si]		;				0600
		inc si				;								0002
		mov di, si			;										0002
		add cx, [bx+di]		;				0606
		mov ax, 4c00h		
		int 21h
codesg ends                   
end start

ここに画像の説明を挿入

7.9 [bx+si+idata]和[bx+di+idata]

bx+変数+定数、より柔軟な
例: 2 次元配列操作: (オフセットを通じて、行と列の概念が実現されます)
idata: 2 次元配列を表します (配列の最初の要素のアドレスを指します)。メモリ内の配列)
bx: 行を表します (ネストされた for では、for
の最初の層の i) di: 例を表します (ネストされた for の for の 2 番目の層の j に相当します)

質問7.5

以下のプログラムを実行後、ax、bx、cxの内容をメモします。

; 2000:1000 BE 00 06 00 6A 22
assume cs:codesg
codesg segment			    ; ax	bx		cx		ds		si		di
start:	mov ax, 2000H	    ; 
   	mov ds, ax          ; 						2000
   	mov bx, 1000H		; 		1000
   	mov si, 0		    ; 								0000
   	mov ax, [bx+2+si]	; 0006
   	inc si				;								0001
   	mov cx, [bx+2+si]	;				6A00
   	inc si				;								0002
   	mov di, si			;										0002
   	add cx, [bx+2+di]	;				8C6A(6A00+226A)
   	mov ax, 4c00h		
   	int 21h
codesg ends                   
end start

ここに画像の説明を挿入

7.10 さまざまなアドレッシングモードの柔軟な適用

  1. [idata]直接定位メモリユニットに使用できるアドレスを表すには定数を使用します。
  2. [bx]间接定位メモリ ユニットに使用できるメモリ アドレスを表す変数を使用します。
  3. [bxtidata]変数と定数を使用してアドレスを表し、起始地址的基础変数と间接定位メモリ ユニットを 1 つで使用できます。
  4. [bx+si]2 つの変数を使用してアドレスを表します。
  5. [bx+sitidata]アドレスは 2 つの変数と 1 つの定数で表されます。

[idata]から まで[bx+sitidata]、より柔軟な方法を使用してメモリ ユニットのアドレスを特定することがわかります。これにより、扱っているデータをより構造化された観点から見ることができます。
本質は、最初に中和式の結果を物理アドレスとして[]計算し、次にそのメモリ部分を指すことです。寄存器常量

質問7.6

datasg セグメント内の各単語の最初の文字を大文字に変更するプログラム
ここに画像の説明を挿入

assume cs:codesg,ds:datasg
datasg segment				;16*6=16字节
	db	'1. file         '	;16字节,末尾空格填充
	db	'2. edit         '  ;16字节,末尾空格填充
	db	'3. search       '  ;16字节,末尾空格填充
	db	'4. view         '  ;16字节,末尾空格填充
	db	'5. options      '  ;16字节,末尾空格填充
	db	'6. help         '  ;16字节,末尾空格填充
datasg ends
codesg segment
 start:	mov ax, datasg
		mov ds, ax
		
		mov bx, 0
		mov cx, 6
 	s:	mov al,[bx+3]		; 取 bx行第3列
		and al, 11011111b	; 转大写
		mov [bx+3], al		; 送回内存
		add bx, 16
		loop s
		
		mov ax, 4c00h		
		int 21h
codesg ends
end start

ここに画像の説明を挿入

質問7.7

プログラミング、datasgセクションの各単語を大文字に変更してください
ここに画像の説明を挿入
このセクションはネガティブな教材であり、2つのループがCXを共有し、無限ループに陥ります。

assume cs:codesg,ds:datasg
datasg segment				;16*4=24字节
	db	'ibm             '	;16字节,末尾空格填充
	db	'dec             '  ;16字节,末尾空格填充
	db	'dos             '  ;16字节,末尾空格填充
	db	'vax             '  ;16字节,末尾空格填充

datasg ends
codesg segment
 start:	mov ax, datasg
		mov ds, ax
		
		mov bx, 0
		mov cx, 4			; 循环4次对应4行
	s0: mov si, 0			; 每行的字符索引从0开始
		mov cx, 3			; 本意是循环3次对应3个字符
							; 但是它覆盖了上面“行”的循环计数。
							; 两层循环共用同一个cx计数,就崩了。
		
 	s:	mov al,[bx+si]		; 取 bx行第3列
		and al, 11011111b	; 转大写
		mov [bx+si], al		; 送回内存
		inc si				; 内层循环j++ 指向下一个字符
		loop s				; 内层循环
		
		add bx, 16			; 外层循环i++ 指向下一歫
		loop s0				; 外层循环
		
		mov ax, 4c00h		
		int 21h
codesg ends
end start

質問7.8

7.7 のバグを修正しました。内側のループが開始されるたびに、外側のループの cx に値を保存し、外側のループのループ命令を実行する前に外側のループの cx の値を復元します。レジスタ dx を使用して cx の値を一時的に保存することができます。改良された手順は次のとおりです。

assume cs:codesg,ds:datasg
datasg segment				;16*4=24字节
	db	'ibm             '	;16字节,末尾空格填充
	db	'dec             '  ;16字节,末尾空格填充
	db	'dos             '  ;16字节,末尾空格填充
	db	'vax             '  ;16字节,末尾空格填充

datasg ends
codesg segment
 start:	mov ax, datasg
		mov ds, ax
		
		mov bx, 0
		mov cx, 4			; 循环4次对应4行
	s0: mov dx, cx			; 将外层循环的 cx 值保存在 dx 中
		mov si, 0			; 每行的字符索引从0开始
		mov cx, 3			; 循环3次对应3个字符
		
 	s:	mov al,[bx+si]		; 取 bx行第3列
		and al, 11011111b	; 转大写
		mov [bx+si], al		; 送回内存
		inc si				; 内层循环j++ 指向下一个字符
		loop s				; 内层循环
		
		add bx, 16			; 外层循环i++ 指向下一行
		mov cx, dx			; 用 dx 中存放的外层循环的计数值恢复 cx
		loop s0				; 外层循环
		
		mov ax, 4c00h		
		int 21h
codesg ends
end start

ここに画像の説明を挿入

質問7.9

プログラムで、datasg セグメント内の各単語の最初の 4 文字を大文字に変更します。

assume cs:codesg,ss:stacksg,ds:datasg

stacksg segment				;16字节
	dw 0,0,0,0,0,0,0,0
stacksg ends

datasg segment				;64字节
	db '1. display      '	;16字节
	db '2. brows        '	;16字节
	db '3. replace      '   ;16字节
	db '4. modify       '   ;16字节
datasg ends

codesg segment	
start:
codesg ends                   
end start

ここに画像の説明を挿入

Lab 6 実践コースの手順

「アセンブリ言語」 - 読書ノート - 実験6実践コースのプログラム

おすすめ

転載: blog.csdn.net/jx520/article/details/130885094