詳細アセンブリ言語のデータ型とデータの定義

シンボルがあるか否かを、データのサイズ(バイト、ワード、ダブルワード、等)に応じて、基本的なアセンブラ内部データ型(組み込みデータ型)のセットを識別する、整数または実数は、そのタイプを記述する。これらのタイプは、オーバーラップのかなりの程度、例えば、DWORD型(32ビット符号なし整数)を有しており、(32ビットの符号付き整数)交換タイプをSDWORDことができます。

 

いくつかは、プログラマは、この値が署名されている、しかし、アセンブラのために必須ではありませんが、プログラムを読むために人々に伝えるSDWORD、言うかもしれません。アセンブラは、オペランドのサイズを見積もります。したがって、例えば、プログラマは、32ビット整数DWORD、SDWORD又はREAL4タイプを指定することができます。

次の表は、内部データ型のすべてのリストを与える、いくつかのIEEEシンボルテーブルエントリは、IEEEコンピュータ学会本当の形式で発行され、標準を指します。

タイプ 使い方
バイト 8ビット符号なし整数、バイトに対するB
SBYTE 8ビットの符号付き整数のために、Sを締結
ワード 16ビット符号なし整数
16ビット符号付き整数
DWORD 32ビット符号なし整数、ダブル(ワード)のためにD
SDWORD 32ビット符号付き整数、符号付きSDビス(単語)を表します
Fワード 48の整数(farポインタプロテクトモード)
QWORD 64ビット整数、Qが表すテトラキス(ワード)
テラバイト 80(10バイト)の整数、T 10バイトの代表
REAL4 32ビット(4バイト)IEEEショート実
REAL8 IEEE実の64ビット(8バイト)の長さ
REAL10 80(10バイト)は、IEEEのリアルタイム拡張しました

データ定義言語

データ定義言語(データ定義文)変数チュー・ストレージ・スペースのためにメモリ内に残っている、とオプションの名前を与えられました。データ定義ステートメントは、変数(テーブル)の内部データ型を定義します。

次のようにデータ定義の構文は次のとおりです。

[名前]ディレクティブ初期化子[、初期化子] ...

次は、データ定義文の例です。

DWORD 12345を数えます

どこで:

  • 名前:仕様に準拠しなければならない変数識別子に割り当てられた名前(オプション)。
  • 指令:データ定義文ディレクティブはBYTE、WORD、DWORD、SBTYE、SWORDまたは上記の表に記載されている他のタイプかもしれません。また、以下の表に定義された従来のデータ指示子であってもよいです。

 

指令 使い方 指令 使い方
DB 8ビット整数 DQ 64ビット整数または実数
DW 16ビット整数 DT 80(10バイト)の整数の定義
DD 32ビット整数または実数     

データ定義は、値が0の場合でも、少なくとも初期値を持っています。その他の初期値は、もしあれば、カンマで区切って指定します。このようなバイトまたはワードなどの整数データ型、初期値(初期の)整数定数または変数タイプ、のための整数表現に一致します。

プログラマは、変数(ランダム化された値)を初期化したくない場合は、シンボルは、初期値として?を使用することができます。バイナリデータにアセンブラによってかかわらず、そのフォーマットのすべての初期値、、。初期値0011 0010B、32H、および50dが同じバイナリ値を持っています。

AddTwoプログラムに変数を追加します。

フロント「整数の加算や減算」セクションでは、AddTwoプログラムを記述し、それは今AddTwoSumとして知られている新しいバージョンを作成しています。このバージョンでは、変数sumを紹介し、それがプログラムの完全なリストに表示されます。

  ; .386 .MODELフラットAddTowSum.asm、4096のExitProcessプロト、dwExitCode .STACK STDCALL:DWORD .DATA和DWORD 0 .CODEメインPROCのMOVのEAX、5アドEAX、6 MOV和、EAX INVOKEのExitProcess、0主ENDP端主に

図13は、各行が実行され、行にブレークポイントを設定し、デバッガプログラムをステップ実行することができます。ライン15の実装後、その値を確認するために、変数sumにカーソルを合わせ。(デバッグセッション中)のWindowsでの[デバッグ]メニューで、[ウォッチ]を選択し、の4つの利用可能なオプション(ウォッチ1、ウォッチ2、Watch3またはウォッチ4)のいずれかを選択しますか、ウォッチウィンドウを開き、開いているプロセスは以下のとおりです。次に、マウスでの表示は、ウォッチウィンドウにドラッグして、変数sumをハイライトします。次の図は、大きな矢印は、実行後に線15で示された例では、合計の電流値を示しています。

詳細アセンブリ言語のデータ型とデータの定義

BYTEデータの定義とSBYTE

バイト(バイトが定義されている)とSByte記憶スペース割り当てられた1つまたは複数の符号なしまたは署名された番号の(定義された符号付きバイト)。各初期値を記憶する場合、それは8ビットでなければなりません。例えば:

  VALUE1 BYTE 'A'、文字定数値2のBYTE 0;符号なしバイト最小値3のBYTE 255;最大符号なしバイトvalue4のSBYTE -128;最小の符号付きバイトVALUE5のSBYTE 127;最大符号付きバイト

疑問符は、実行時にその変数に値を代入を意味し、初期化されていない変数の初期値になります(?):

value6のBYTE?

あるいは名前は、セグメントの先頭からオフセット変数に変数識別子を含む、ラベルです。例えば、データセグメント値1であれば0000のオフセット、および0001のオフセットで、1バイトのメモリに、自動的に値2です。

VALUE1 BYTE 10hの
値2バイト20H

DBディレクティブは、符号付きまたは符号なしの8ビット変数を定義することができます。

VAL1 DB 255;符号なしバイト
val2のDB -128;符号付きバイト

1)マルチ初期値

如果同一个数据定义中使用了多个初始值,那么它的标号只指出第一个初始值的偏移量。在下面的例子中,假设 list 的偏移量为 0000。那么,数值 10 的偏移量就为 0000, 20 的偏移量为 0001,30 的偏移量为 0002,40 的偏移量为 0003:

list BYTE 10,20,30,40

下图给出了字节序列 list,显示了每个字节及其偏移量。

詳細アセンブリ言語のデータ型とデータの定義

并不是所有的数据定义都要用标号。比如,在 list 后面继续添加字节数组,就可以在下一行定义它们:

  list BYTE 10,20,30,40       BYTE 50,60,70,80       BYTE 81,82,83,84

在单个数据定义中,其初始值可以使用不同的基数。字符和字符串常量也可以自由组合。在下面的例子中,list1 和 list2 有相同的内容:

  list1 BYTE 10, 32, 41h, 00100010b  list2 BYTE 0Ah, 20h, 'A', 22h

2) 定义字符串

定义一个字符串,要用单引号或双引号将其括起来。最常见的字符串类型是用一个空字节(值为0)作为结束标记,称为以空字节结束的字符串,很多编程语言中都使用这种类型的字符串:

  greeting1 BYTE "Good afternoon",0  greeting2 BYTE 'Good night',0

每个字符占一个字节的存储空间。对于字节数值必须用逗号分隔的规则而言,字符串是一个例外。如果没有这种例外,greeting1 就会被定义为:

greeting1 BYTE 'G', 'o', 'o', 'd'….etc.

这就显得很冗长。一个字符串可以分为多行,并且不用为每一行都添加标号:

  greeting1 BYTE "Welcome to the Encryption Demo program "            BYTE "created by Kip Irvine.",0dh, 0ah            BYTE "If you wish to modify this program, please "            BYTE "send me a copy.",0dh,0ah,0

十六进制代码 0Dh 和 0Ah 也被称为 CR/LF (回车换行符)或行结束字符。在编写标准输出时,它们将光标移动到当前行的下一行的左侧。

行连续字符()把两个源代码行连接成一条语句,它必须是一行的最后一个字符。下面的语句是等价的:

greeting1 BYTE "Welcome to the Encryption Demo program "

greeting1 
BYTE "Welcome to the Encryption Demo program "

3) DUP 操作符

DUP 操作符使用一个整数表达式作为计数器,为多个数据项分配存储空间。在为字符串或数组分配存储空间时,这个操作符非常有用,它可以使用初始化或非初始化数据:

  BYTE 20 DUP ( 0 )      ;20 个字节,值都为 0  BYTE 20 DUP ( ? )      ;20 个字节,非初始化  BYTE 4 DUP ( "STACK" ) ; 20 个字节:

定义 WORD 和 SWORD 数据

WORD(定义字)和 SWORD(定义有符号字)伪指令为一个或多个 16 位整数分配存储空间:

  word1 WORD 65535    ;最大无符号数  word2 SWORD -32768  ;最小有符号数  word3 WORD ?        ;未初始化,无符号

也可以使用传统的 DW 伪指令:

  val1 DW 65535   ;无符号  val2 DW -32768  ;有符号

16 位字数组通过列举元素或使用 DUP 操作符来创建字数组。下面的数组包含了一组数值:

myList WORD 1,2,3,4,5

下图是一个数组在内存中的示意图,假设 myList 起始位置偏移量为0000。由于每个数值占两个字节,因此其地址递增量为 2。

詳細アセンブリ言語のデータ型とデータの定義

DUP 操作符提供了一种方便的方法来声明数组:

array WORD 5 DUP (?) ; 5 个数值,未初始化

定义 DWORD 和 SDWORD 数据

DWORD(定义双字)和 SDWORD(定义有符号双字)伪指令为一个或多个 32 位整数分配存储空间:

  val1 DWORD 12345678h    ;无符号  val2 SDWORD -2147483648 ;有符号  val3 DWORD 20 DUP (?)   ;无符号数组

传统的 DD 伪指令也可以用来定义双字数据:

  val1 DD 12345678h ;无符号  val2 DD -2147483648 ;有符号

DWORD 还可以用于声明一种变量,这种变量包含的是另一个变量的 32 位偏移量。如下所示,pVal 包含的就是 val3 的偏移量:

pVal DWORD val3

32 位双字数组

现在定义一个双字数组,并显式初始化它的每 一个值:

myList DWORD 1,2,3,4,5

下图给岀了这个数组在内存中的示意图,假设 myList 起始位置偏移量为 0000,偏移量增量为 4。

詳細アセンブリ言語のデータ型とデータの定義

定义 QWORD 数据

QWORD(定义四字)伪指令为 64 位(8 字节)数值分配存储空间:

quad1 QWORD 1234567812345678h

传统的 DQ 伪指令也可以用来定义四字数据:

quad1 DQ 1234567812345678h

定义压缩 BCD(TBYTE)数据

Intel 把一个压缩的二进制编码的十进制(BCD, Binary Coded Decimal)整数存放在一个 10 字节的包中。每个字节(除了最高字节之外)包含两个十进制数字。在低 9 个存储字节中,每半个字节都存放了一个十进制数字。最高字节中,最高位表示该数的符号位。如果最高字节为 80h,该数就是负数;如果最高字节为 00h,该数就是正数。整数的范围是 -999 999 999 999 999 999 到 +999 999 999 999 999 999。

示例下表列出了正、负十进制数 1234 的十六进制存储字节,排列顺序从最低有效字节到最高有效字节:

十进制数值 存储字节
+1234 34 12 00 00 00 00 00 00 00 00
-1234 34 12 00 00 00 00 00 00 00 80

MASM 使用 TBYTE 伪指令来定义压缩 BCD 变量。常数初始值必须是十六进制的,因为,汇编器不会自动将十进制初始值转换为 BCD 码。下面的两个例子展示了十进制 数 -1234 有效和无效的表达方式:

  intVal TBYTE 800000000000001234h ;有效  intVal TBYTE -1234               ;无效

第二个例子无效的原因是 MASM 将常数编码为二进制整数,而不是压缩 BCD 整数。

如果想要把一个实数编码为压缩 BCD 码,可以先用 FLD 指令将该实数加载到浮点寄存器堆栈,再用 FBSTP 指令将其转换为压缩 BCD 码,该指令会把数值舍入到最接近的整数:

  .data  posVal REAL8 1.5  bcdVal TBYTE ?    .code  fid posVal ;加载到浮点堆栈  fbstp bcdVal ;向上舍入到 2,压缩 BCD 码值

如果 posVal 等于 1.5,结果 BCD 值就是 2。

定义浮点类型

REAL4 定义 4 字节单精度浮点变量。REAL8 定义 8 字节双精度数值,REAL10 定义 10 字节扩展精度数值。每个伪指令都需要一个或多个实常数初始值:

  rVal1 REAL4 -1.2  rVal2 REAL8 3.2E-260  rVal3 REAL10 4.6E+4096  ShortArray REAL4 20 DUP(0.0)

下表描述了标准实类型的最少有效数字个数和近似范围:

数据类型 有效数字 近似范围
短实数 6 1.18x 10-38 to 3.40 x 1038
长实数 15 2.23 x 10-308 to 1.79 x 10308
扩展精度实数 19 3.37 x 10-4932 to 1.18 x 104932

DD、DQ 和 DT 伪指令也可以定义实数:

  rVal1 DD -1.2      ;短实数  rVal2 DQ 3.2E-260  ;长实数  rVal3 DT 4.6E+4096 ;扩展精度实数

MASM 汇编器包含了诸如 wal4 和 real8 的数据类型,这些类型表明数值是实数。更准确地说,这些数值是浮点数,其精度和范围都是有限的。从数学的角度来看,实数的精度和大小是无限的。

变量加法程序

到目前为止,本节的示例程序实现了存储在寄存器中的整数加法。现在已经对如何定义数据有了一些了解,那么可以对同样的程序进行修改,使之实现三个整数变量相加,并将和数存放到第四个变量中。

  ;AddTowSum.asm    .386  .model flat,stdcall  .stack 4096  ExitProcess PROTO, dwExitCode:DWORD    .data  firstval DWORD 20002000h  secondval DWORD 11111111h  thirdval DWORD 22222222h  sum DWORD 0    .code  main PROC      mov eax,firstval      add eax,secondval      add eax,thirdval      mov sum,eax        INVOKE ExitProcess,0  main ENDP  END main

注意,已经用非零数值对三个变量进行了初始化(9〜11 行)。16〜18 行进行变量相加。x86 指令集不允许将一个变量直接与另一个变量相加,但是允许一个变量与一个寄存器相加。这就是为什么 16〜17 行用 EAX 作累加器的原因:

mov eax,firstval
add eax,secondval

第 17 行之后,EAX 中包含了 firstval 和 secondval 之和。接着,第 18 行把 thirdval 加到 EAX 中的和数上:

add eax,thirdval

最后,在第 19 行,和数被复制到名称为 sum 的变量中:

mov sum,eax

作为练习,鼓励大家在调试会话中运行本程序,并在每条指令执行后检查每个寄存器。最终和数应为十六进制的 53335333。

在调试会话过程中,如果想要变量显示为十六进制,则按下述步骤操作:鼠标在变量或寄存器上悬停 1 秒,直到一个灰色矩形框出现在鼠标下。右键点击该矩形框,在弹出菜单中选择 Hexadecimal Display。

小端顺序

x86 处理器在内存中按小端(little-endian)顺序(低到高)存放和检索数据。最低有效字节存放在分配给该数据的第一个内存地址中,剩余字节存放在随后的连续内存位置中。考虑一个双字 12345678h。如果将其存放在偏移量为 0000 的位置,则 78h 存放在第一个字节,56h 存放在第二个字节,余下的字节存放地址偏移量为 0002 和 0003,如下图所示。

詳細アセンブリ言語のデータ型とデータの定義

其他有些计算机系统采用的是大端顺序(高到低)。 下图展示了 12345678h 从偏移量 0000 开始的大端顺序存放。

詳細アセンブリ言語のデータ型とデータの定義

声明未初始化数据

.DATA ? 伪指令声明未初始化数据。当定义大量未初始化数据时,.DATA ? 伪指令减少了编译程序的大小。例如,下述代码是有效声明:

  .data  smallArray DWORD 10 DUP (0) ;40 个字节  .data?  bigArray DWORD 5000 DUP ( ? ) ;20 000 个字节,未初始化

而另一方面,下述代码生成的编译程序将会多岀 20 000 个字节:

  .data  smallArray DWORD 10 DUP ( 0 )  ; 40 个字节  bigArray DWORD 5000 DUP ( ? )  ; 20 000 个字节

代码与数据混合汇编器允许在程序中进行代码和数据的来回切换。比如,想要声明一个变量,使其只能在程序的局部区域中使用。下述示例在两个代码语句之间插入了一个名为 temp 的变量:

  .code  mov eax,ebx  .data  temp DWORD ?  .code  mov temp,eax

尽管 temp 声明的出现打断了可执行指令流,MASM 还是会把 temp 放在数据段中,并与保持编译的代码段分隔开。然而同时,混用 .code 和 .data 伪指令会使得程序变得难以阅读。

下一篇:等号伪指令

强力推荐阅读文章

年薪40+W的大数据开发【教程】,都在这儿!

おすすめ

転載: blog.csdn.net/Javaxuxuexi/article/details/93312804