8086带I / O的汇编数组

时间:2015-06-09 06:08:56

标签: assembly

我想知道是否可以重新定义数组的大小,或者只是通过代码段创建一个新的数组。这是我到目前为止所做的:

.DATA
prompt1 db "Please enter a number which will ressemble the N of the array",13,10,'$'
value db ?

.CODE
DisplayIO proc
lea DX, prompt1
mov AH, 09h
int 21h
mov AH, 08h
int 21h
ret
DisplayIO endP
call DisplayIO
sub AL, 30h
mov value, AH

我正在尝试做的,基本上是创建一个大小为value

的数组

2 个答案:

答案 0 :(得分:1)

在DOS中,您可以使用系统调用(int 21h, ah = 0x48)来保留所选大小的片段(所有片段都是16字节的倍数)。还记得free the block使用int 21h,ah = 0x49。

  

INT 21,48 - 分配内存
      AH = 48h
      BX =请求的内存段落数

on return:
AX = segment address of allocated memory block (MCB + 1para)
   = error code if CF set  (see DOS ERROR CODES)
BX = size in paras of the largest block of memory available
     if CF set, and AX = 08 (Not Enough Mem)
CF = 0 if successful
   = 1 if error


- returns segment address of allocated memory block AX:0000
- each allocation requires a 16 byte overhead for the MCB
- returns maximum block size available if error

或者您可以从代码/数据静态分配最大长度缓冲区并构建自己的malloc。

答案 1 :(得分:0)

正如 Aki Suihkonen 所说,分配内存是解决方案。我用EMU8086开发了下一个示例:它向用户询问一个数字(数组大小,以字节为单位),然后创建一个该大小的数组。例如,输入20表示20字节的数组,或输入40表示20字的数组。这是代码(有很多评论可以帮助您理解):

.model small

.stack 100h

.data

msg1      db 'Enter the size in byte of the array: $'
size_str  db 6,?,6 dup(?) ;ARRAY SIZE IN STRING.
size_num  dw ?            ;ARRAY SIZE IN NUMERIC.
array_seg dw ?            ;ARRAY ON ALLOCATED MEMORY.

;-----------------------------------------------------------------

.code
start:

;INITIALIZE DATA SEGMENT.
  mov  ax, @data
  mov  ds, ax

;DISPLAY MESSAGE.
  mov  dx, offset msg1       ;MESSAGE TO DISPLAY.
  call printf

;CAPTURE NUMBER AS STRING.
  mov  dx, offset size_str   ;BUFFER TO STORE CAPTURED STRING.
  call scanf

;CONVERT CAPTURED NUMBER FROM STRING TO NUMERIC.
  mov  si, offset size_str   ;STRING TO CONVERT.
  call string2number         ;NUMBER RETURNS IN BX.
  mov  size_num, bx          ;PRESERVE RETURNED VALUE.

;ALLOCATE MEMORY FOR THE ARRAY.
  call build_array    

;EXAMPLE : FILL ARRAY WITH 0.
  call zeroes

;WAIT FOR ANY KEY.    
  mov  ah, 7
  int  21h

;FINISH PROGRAM.
  mov  ax, 4c00h
  int  21h

;-----------------------------------------------------------------
;PARAMETER : DX POINTING TO '$' FINISHED STRING.

printf proc
  mov  ah, 9
  int  21h
  ret
printf endp    

;-----------------------------------------
;PARAMETER : DX POINTING TO BUFFER TO STORE STRING.

scanf proc
  mov  ah, 0Ah
  int  21h
  ret
scanf endp    

;-----------------------------------------------------------------
;CONVERT STRING TO NUMBER.
;PARAMETER : SI POINTING TO STRING CAPTURED WITH 0AH.
;RETURN    : NUMBER IN BX.

string2number proc
;MAKE SI TO POINT TO THE LEAST SIGNIFICANT DIGIT.
  inc  si ;POINTS TO THE NUMBER OF CHARACTERS ENTERED.
  mov  cl, [ si ] ;NUMBER OF CHARACTERS ENTERED.                                         
  mov  ch, 0 ;CLEAR CH, NOW CX==CL.
  add  si, cx ;NOW SI POINTS TO LEAST SIGNIFICANT DIGIT.
;CONVERT STRING.
  mov  bx, 0
  mov  bp, 1 ;MULTIPLE OF 10 TO MULTIPLY EVERY DIGIT.
repeat:         
;CONVERT CHARACTER.                    
  mov  al, [ si ] ;CHARACTER TO PROCESS.
  sub  al, 48 ;CONVERT ASCII CHARACTER TO DIGIT.
  mov  ah, 0 ;CLEAR AH, NOW AX==AL.
  mul  bp ;AX*BP = DX:AX.
  add  bx, ax ;ADD RESULT TO BX. 
;INCREASE MULTIPLE OF 10 (1, 10, 100...).
  mov  ax, bp
  mov  bp, 10
  mul  bp ;AX*10 = DX:AX.
  mov  bp, ax ;NEW MULTIPLE OF 10.  
;CHECK IF WE HAVE FINISHED.
  dec  si ;NEXT DIGIT TO PROCESS.
  loop repeat ;COUNTER CX-1, IF NOT ZERO, REPEAT.

  ret 
string2number endp

;-----------------------------------------------------------------
;TO BUILD THE ARRAY IS NECESSARY TO ALLOCATE MEMORY. MEMORY IS
;ALLOCATED IN BLOCKS OF 16 BYTES CALLED "PARAGRAPHS". IT'S NOT
;POSSIBLE TO ALLOCATE ODD NUMBERS, ONLY MULTIPLES OF 16. FOR
;EXAMPLE, FOR AN ARRAY OF 20 BYTES IT'S NECESSARY TO ALLOCATE TWO
;PARAGRAPHS (12 BYTES WASTED).

build_array proc
;FIND OUT HOW MANY PARAGRAPHS WILL BE NEEDED DIVIDING THE
;REQUESTED MEMORY SIZE BY 16.
  mov  ax, size_num     ;REQUESTED MEMORY.
  mov  bl, 16           ;DIVISOR.
  div  bl               ;AX / 16 : AL=QUOTIENT, AH=REMAINDER.

;IF REMAINDER == 0, SIZE_NUM IS MULTIPLE OF 16, IF REMAINDER != 0,
;ADD ANOTHER PARAGRAPH (SOME BYTES WASTED).
  cmp  ah, 0
  je   is_multiple      ;IF AH == 0 : JUMP.
;IF NO JUMP, REMAINDER != 0.
  inc  al               ;ANOTHER PARAGRAPH WILL BE NEEDED.

is_multiple:

;ALLOCATE THE MEMORY PARAGRAPHS.
  mov  bl, al           ;NUMBER OF PARAGRAPHS.
  mov  bh, 0            ;CLEAR BH TO USE BX.
  call allocate  

  ret
build_array endp

;-----------------------------------------------------------------
;ALLOCATES "N" PARAGRAPHS OF MEMORY. ONE PARAGRAPH = 16 BYTES.
;THE RETURNED MEMORY IS A SEGMENT, "ES" CAN BE USED TO POINT TO IT.
;PARAMETER : BX = HOW MANY PARAGRAPHS TO ALLOCATE.
;RETURN    : VARIABLE "ARRAY_SEG" WITH ADDRESS OF ALLOCATED SEGMENT.

allocate proc
  mov  ah, 48h          ;SERVICE TO ALLOCATE MEMORY.
  int  21h              ;RETURNS AX = SEGMENT OF MEMORY ALLOCATED.
  mov  array_seg, ax 
  ret
allocate endp  

;-----------------------------------------------------------------
;FILL ARRAY WITH ZEROES.

zeroes proc
  mov  ax, array_seg    ;REMEMBER : ARRAY IS A SEGMENT,
  mov  es, ax           ;THAT'S WHY "ES" MUST BE USED.

  mov  si, 0            ;SI = INDEX FOR THE ARRAY.
  mov  cx, size_num     ;SIZE IN BYTES OF THE ARRAY.
  mov  dl, 0            ;VALUE TO FILL ARRAY.

filling:
  mov  [ es:si ], dl    ;STORE ZERO IN CURRENT POSITION.
  inc  si               ;MOVE SI TO NEXT POSITION.
  loop filling          ;CX-1. IF CX > 0 : REPEAT.

  ret
zeroes endp

;-----------------------------------------------------------------

end start

一些注意事项:

  • 用户输入的数字必须除以16,因为内存以16个字节的块分配。
  • 数组存储在自己的内存段中(不在数据段中),这就是必须使用ES来访问它的原因。
  • 该数字从键盘捕获为字符串,然后转换为数字。