|
NGASM 8086/8088 Assembler v1.4 Beta 2 NGASM 8086/8088 Assembler version 1.4 Beta 2 supports the operators BYTE (or BYTE PTR), WORD (or WORD PTR), DWORD (or DWORD PTR), OFFSET and FAR in the code part of an NGASM source code file. With NGASM you need not wrestle with operator precedence rules.
Operators in the data declaration part The DUP Operator The DUP operator tells the assembler to duplicate a value, given within parenthesis, a specified number of times in memory. This operator is used in conjunction with the data declaration directives DB, DW, and DD. Syntax: count DUP ( initializer ) count is the number of times to duplicate the initializer initializer is a single decimal or hexadecimal, byte or word or dword value as permitted by the data declaration directive or a single ? character. If the initializer is a ?, memory will be initialized with NULL values. The initializer must be surrounded by parenthesis.Example: array1 DB 1000 DUP (0) array2 DW 10 DUP (1234h) array3 DD 10 DUP (?) array4 DD 10 DUP (4294967295) The OFFSET Operator in the Data part The OFFSET operator returns the address of the label specified. Syntax: OFFSET label label is a label defined somewhere above or below.Example: JMP MAIN ;MAIN is a forward referenced label ;This is the data declaration part pointer_to_msg DW OFFSET msg ;msg is a forward referenced label ;OFFSET Operator used in the Data part ;of file. Here, msg is referenced before ;it is defined. This is an example of ;Forward Reference. ;This is the code part MAIN: ;MAIN is defined here MOV AH,9 MOV DX,pointer_to_msg INT 21h INT 20h msg DB 'Happy New Year',0Dh,0Ah,24h ;msg is defined hereNormally the above example must be coded like this: JMP MAIN ;This is the data declaration part msg DB 'Happy New Year',0Dh,0Ah,24h ;This is the code part MAIN: MOV AH,9 MOV DX,OFFSET msg ;This is OFFSET operator in Code part INT 21h INT 20hThe THIS BYTE, THIS WORD, THIS DWORD Operators These operators return the value of the current location counter (i.e. current memory address). These operators are used in conjunction with the EQUate directive only. Syntax label EQU THIS BYTE label EQU THIS WORD label EQU THIS DWORDExample
JMP MAIN
addr1 EQU THIS BYTE
DB 10
addr2 EQU THIS WORD
DW 1000h
addr3 EQU THIS DWORD
DD 12345678h
MAIN:
MOV AL,addr1 ;assembles as: MOV AL,[0103h]
MOV AX,addr2 ;assembles as: MOV AX,[0104h]
LES DI,addr3 ;assembles as: LES DI,[0106h]
INT 20h
The $ OperatorThe $ operator returns the value of the current location counter and is used, in NGASM source code files, in conjunction with the EQUate directive only. Syntax: label EQU $Example:
JMP MAIN
address1 EQU $
DB 'Good Luck',13,10,24h
MAIN:
MOV AH,9
MOV DX,address1 ;generated code: MOV DX,0103h
INT 21h
INT 20h
Operators in the code partSize Specifier Operators: The BYTE or BYTE PTR Operator The WORD or WORD PTR Operator The DWORD or DWORD PTR Operator These size specifier operators force the operand to the specified type. If we put it otherwise, these size specifier operators tell the assembler to consider the (nearby) operand as a byte pointer when the operator specified is BYTE or BYTE PTR, or as a word pointer when the operator specified is WORD or WORD PTR, or as a dword pointer when the operator specified is DWORD or DWORD PTR. NGASM mostly learns from context the size of a particular operand. Anyway in some cases the size specifier operators are needed. EQUATEs and a variable for use in the code fragment below BUFFER_1 DB 13 DUP (0) BUF_1_END EQU $ DISPLACEMENT_1 EQU 9 MEMORY_LOCATION_1 EQU 1234hNo Assembler can ascertain the size of operand from EQUates, literal numerical constants used as displacement, and index registers or a mix of them. In such cases of indirect addressing, the programmer should specify the size of the operand. That is, if you access/modify a word you use the WORD operator; if you access/modify a byte you use the BYTE operator. The following instruction statements employ indirect addressing and so the programmer should specify the size of the operand. ;you DECrement a BYTE DEC BYTE [100h] ;you DECrement a BYTE DEC BYTE [MEMORY_LOCATION_1] ;you DECrement a WORD DEC WORD [MEMORY_LOCATION_1+5] ;you INCrement a BYTE INC BYTE [100h] ;you INCrement a BYTE INC BYTE [BX] ;you INCrement a WORD INC WORD [BX+DISPLACEMENT_1] ;you INCrement a WORD INC WORD [BX+SI+DISPLACEMENT_1]IF the size specifier operator (BYTE or WORD) is NOT used in the assembler statements above, they assemble as follows: DEC BYTE PTR [100h] DEC BYTE PTR [1234] DEC BYTE PTR [1239] INC BYTE PTR [100h] INC WORD PTR [BX] INC WORD PTR [BX+09] INC WORD PTR [BX+SI+09] The OFFSET Operator in the Code part The OFFSET operator returns the address of the label specified. It is used in conjunction with the instruction statements. Syntax: mnemonic operand, OFFSET label mnemonic is the short name for an instruction. operand is a Reg16 or Mem16. label is a label defined somewhere above. It can't be a label below the current instruction statement.Example: JMP MAIN msg1 DB 'This gets printed twice.',0Dh,0Ah,'$' ;$ = 24h msg_ptr DW OFFSET msg1 ;OFFSET Operator used in the Data part of file MAIN: MOV AH,9 MOV DX,OFFSET msg1 ;OFFSET Operator used in the Code part of file INT 21h MOV DX,msg_ptr INT 21h INT 20h The FAR Operator The FAR operator denotes that the following item is a FAR pointer. A FAR pointer is made up of a segment and offset pair in the order offset, segment. Syntax: JMP FAR label CALL FAR label label is a label defined somewhere above or below. JMP FAR segment:offset CALL FAR segment:offset segment is either an Imm16 (a literal word-sized number) or an EQUate. offset is either an Imm16 (a literal word-sized number) or an EQUate. The segment:offset pair must actually be the address of some code. JMP FAR [operand] CALL FAR [operand] operand is any one of the base or index registers, Mem16, Imm16, or any one of the base or index register+Mem16+Imm16 combinations surrounded by square brackets.Example: JMP FAR CS:[Old_INT_9_OFFSET] ;when Old_INT_9_OFFSET reserves two ;DW's, 1st one for Offset and next ;one for Segment. You can name the ;second DW appropriately as ;Old_INT_9_SEGMENT The Segment Override Operator ":" The Segment Override Operator ":" specifies that instead of the default segment the specified segment is where the memory location pointed to by the operand is. For example, imagine a small TSR which has a few variables which need to be accessed, when the TSR gets execution control, without changing the DS Register to point to the TSR's segment. This is done by using the Segment Override Operator as in the example below. As the default segment for any variable is DS, we need to make the code access the variable in the CS segment (assume that we are not changing the DS Register to point to the TSR's segment when the TSR gets activated (gets execution control). Example: CS: JMP FAR [Old_INT_9_OFFSET] (or) JMP FAR CS:[Old_INT_9_OFFSET] The LODSB instruction (LODSW instruction too) accesses data in the DS segment by default. The LODSB instruction loads a byte from the memory location pointed to by the SI register. You can make the instruction load a byte from the ES or CS segment by specifying a Segment Override as in the example below. You can write the code below inside DEBUG.EXE after entering the A (Assemble) command at DEBUG's hyphen prompt (-). Then type P at DEBUG's hyphen prompt (-) to execute the code. Watch the AX Register before and after you hit P. Example: LODSB MOV AX,6666h ;instead of 6666h, use a segment address ;that has some junk so that you get some byte in AL ;when the following LODSB executes. MOV ES,AX ES: LODSB CS: LODSB Watch what you get in the AL Register (that is, low order byte of the AX Register). And watch the SI Register after each LODSB executes. The Array Index Operator "[ ]" The usage of Array Index Operator [ ] in the following examples is self-explanatory. But you cannot use it to access multi-dimensional arrays. Example: MOV AX,[BX+SI+5] ;DS Register points to the base segment (or the equivalent) MOV AX,[BX][SI][5] ;DS Register points to the base segment |
|