【8086汇编基础】05--常用函数库文件--emu8086.inc

8086汇编语言初学者教程(第5部分)

常用函数库 - emu8086.inc 

通过引用一些常用函数,可以使你编程更加方便。

在你的程序中使用其他文件中的函数的方法是

INCLUDE后面接上你要引用的文件名。编译器

会自动在你源程序所在的文件夹中查找你引用

的文件,如果没有找到,它将搜索Inc 文件夹。

通常你无法完全理解 emu8086.inc(位于Inc文件夹)

但是这没有关系,你只用知道它能做什么就足够了。

要使用emu8086.inc中的函数,你应当在你程序的开

头加上

include 'emu8086.inc' 



emu8086.inc 定义了如下的宏:

  • PUTC char - 将一个ascii字符输出到光标当前位值,只有一个
                       参数的宏

  • GOTOXY col, row - 设置当前光标位置,有两个参数

  • PRINT string - 输出字符串,一个参数

  • PRINTN string - 输出字符串,一个参数。与print功能相同,
                            不同在于输出之后自动回车

  • CURSOROFF - 关闭文本光标

  • CURSORON - 打开文本光标

使用上述宏的方法是:在你需要的位值写上宏名称加上参数。例如:



include emu8086.inc



ORG 100h



PRINT 'Hello World!'



GOTOXY 10, 5



PUTC 65 ; 65 - ASCII 码的 'A'

PUTC 'B'



RET ; 返回操作系统

END ; 停止编译器


当编译器运行你的代码时,它首先找到声明中的

emu8086.inc文件,然后将代码中的宏用实际的

代码替换掉。通常来说,宏都是比较小的代码段,

经常使用宏会使得你的可执行程序特别大

(对于降低文件大小来说使用过程更好)



emu8086.inc 同样定义了如下过程:

  • PRINT_STRING - 在当前光标位置输出一个字符串字符串地址由DS:SI 寄存器给出使用时,需要在END前面声明DEFINE_PRINT_STRING 才能使用.

  • PTHIS - 在当前光标位置输出一个字符串(同 PRINT_STRING)

    一样,不同之处在于它是从堆栈接收字符串。字符串终止符

    应在call之后定义。例如

       CALL PTHIS
       db 'Hello World!', 0 

    使用时,需要在 END 前面声明 DEFINE_PTHIS 。
  • GET_STRING - 从用户输入得到一个字符串,输入的字符串写入 DS:DI 指出的缓冲,缓冲区的大小由 DX设置。回车作为输入结束。使用时,需要在END前面声明    DEFINE_GET_STRING 。

  • CLEAR_SCREEN - 清屏过程(滚过整个屏幕),然后将光标设置在左上角. 使用时,需要在END前面声明DEFINE_CLEAR_SCREEN  。
     
  • SCAN_NUM - 取得用户从键盘输入的多位有符号数,并将输入存放
    CX寄存器。 使用时,需要在 END前面声明      DEFINE_SCAN_NUM

  • PRINT_NUM - 输出AX寄存器中的有符号数
    使用时,需要在END 前面声明 DEFINE_PRINT_NUM以及 DEFINE_PRINT_NUM_UNS.

  • PRINT_NUM_UNS - 输出AX寄存器中的无符号数。使用时,需要在END 前面声明DEFINE_PRINT_NUM_UNS.

使用上述过程,必须在你源程序的底部(但是在END之前!!!)声明这些函数,使用CALL指令后面接上过程名称来调用。例如:

include 'emu8086.inc'



ORG 100h



LEA SI, msg1 ; 要求输入数字

CALL print_string ;

CALL scan_num ; 读取数字放入cx



MOV AX, CX ; CX存放数值拷贝到AX



; 输入如下字符

CALL pthis

DB 13, 10, 'You have entered: ', 0



CALL print_num ; 输出 AX中的字符



RET ; 返回操作系统



msg1 DB 'Enter the number: ', 0



DEFINE_SCAN_NUM

DEFINE_PRINT_STRING

DEFINE_PRINT_NUM

DEFINE_PRINT_NUM_UNS ; print_num函数要求的

DEFINE_PTHIS



END ; 结束



首先,编译器运行声明(对于宏只是展开)。当编译器遇到CALL指令,它

将用过程声明中的地址来替代过程名。程序在执行过程中遇到这个过程,便

会直接跳转到过程。这是非常有用的,比如,即使在你的代码中执行100次

一个过程,编译后的可执行文件也不会因此而增大多少。这样看起来很

划算,是不是?后面你会学到更多的,现在只需要了解一点点基本原理。

 

emu8086.inc文件内容如下:

emu8086.inc
  1 ; emu8086.inc - macro definitions library for easy input/output

  2 

  3 

  4 

  5 

  6 ; Note, that some declarations of "emu8086.inc" are macro procedure declarations, and you

  7 ; have to use "DEFINE_..." macro somewhere in your program if you want to use these functions:

  8 

  9 ;   CALL SCAN_NUM

 10 ;   CALL PRINT_STRING

 11 ;   CALL PTHIS

 12 ;   CALL GET_STRING

 13 ;   CALL CLEAR_SCREEN

 14 ;   CALL PRINT_NUM

 15 ;   CALL PRINT_NUM_UNS

 16 

 17 ; You can define all these procedures in your source code, but compilation time may slow down

 18 ; sufficiently because of that, only declare functions that you plan to use:

 19 

 20 

 21 ;   DEFINE_SCAN_NUM

 22 ;   DEFINE_PRINT_STRING

 23 ;   DEFINE_PTHIS

 24 ;   DEFINE_GET_STRING

 25 ;   DEFINE_CLEAR_SCREEN

 26 ;   DEFINE_PRINT_NUM

 27 ;   DEFINE_PRINT_NUM_UNS

 28 

 29 ;  The above declarations should be made in  your code once only! Better somewhere

 30 ;  in the end of your file, but before "END"  directive. You can also declare them

 31 ;  in the beginning of the file, but it should  be after "ORG 100h" directive for COM files,

 32 ;  or inside the code segment for EXE files.

 33 

 34 

 35 

 36 

 37 

 38 

 39 

 40 

 41 

 42 ; this macro prints a char in AL and advances

 43 ; the current cursor position:

 44 PUTC    MACRO   char

 45         PUSH    AX

 46         MOV     AL, char

 47         MOV     AH, 0Eh

 48         INT     10h     

 49         POP     AX

 50 ENDM

 51 

 52 

 53 ; this macro prints a string that is given as a parameter, example:

 54 ; PRINT 'hello world!'

 55 ; new line is NOT added.

 56 PRINT   MACRO   sdat

 57 LOCAL   next_char, s_dcl, printed, skip_dcl

 58 

 59 PUSH    AX      ; store registers...

 60 PUSH    SI      ;

 61 

 62 JMP     skip_dcl        ; skip declaration.

 63         s_dcl DB sdat, 0

 64 

 65 skip_dcl:

 66         LEA     SI, s_dcl

 67         

 68 next_char:      

 69         MOV     AL, CS:[SI]

 70         CMP     AL, 0

 71         JZ      printed

 72         INC     SI

 73         MOV     AH, 0Eh ; teletype function.

 74         INT     10h

 75         JMP     next_char

 76 printed:

 77 

 78 POP     SI      ; re-store registers...

 79 POP     AX      ;

 80 ENDM

 81 

 82 

 83 ; this macro prints a string that is given as a parameter, example:

 84 ; PRINTN 'hello world!'

 85 ; the same as PRINT, but new line is automatically added.

 86 PRINTN   MACRO   sdat

 87 LOCAL   next_char, s_dcl, printed, skip_dcl

 88 

 89 PUSH    AX      ; store registers...

 90 PUSH    SI      ;

 91 

 92 JMP     skip_dcl        ; skip declaration.

 93         s_dcl DB sdat, 13, 10, 0

 94 

 95 skip_dcl:

 96         LEA     SI, s_dcl

 97         

 98 next_char:      

 99         MOV     AL, CS:[SI]

100         CMP     AL, 0

101         JZ      printed

102         INC     SI

103         MOV     AH, 0Eh ; teletype function.

104         INT     10h

105         JMP     next_char

106 printed:

107 

108 POP     SI      ; re-store registers...

109 POP     AX      ;

110 ENDM

111 

112 

113 ; turns off the cursor:

114 CURSOROFF       MACRO

115         PUSH    AX

116         PUSH    CX

117         MOV     AH, 1

118         MOV     CH, 28h

119         MOV     CL, 09h

120         INT     10h

121         POP     CX

122         POP     AX

123 ENDM

124 

125 

126 

127 ; turns on the cursor:

128 CURSORON        MACRO

129         PUSH    AX

130         PUSH    CX

131         MOV     AH, 1

132         MOV     CH, 08h

133         MOV     CL, 09h

134         INT     10h

135         POP     CX

136         POP     AX

137 ENDM

138 

139 ; sets current cursor

140 ; position:

141 GOTOXY  MACRO   col, row

142         PUSH    AX

143         PUSH    BX

144         PUSH    DX

145         MOV     AH, 02h

146         MOV     DH, row

147         MOV     DL, col

148         MOV     BH, 0

149         INT     10h

150         POP     DX

151         POP     BX

152         POP     AX

153 ENDM

154 

155 

156 ;***************************************************************

157 

158 ; This macro defines a procedure that gets the multi-digit SIGNED number from the keyboard,

159 ; and stores the result in CX register:

160 DEFINE_SCAN_NUM         MACRO

161 LOCAL make_minus, ten, next_digit, set_minus

162 LOCAL too_big, backspace_checked, too_big2

163 LOCAL stop_input, not_minus, skip_proc_scan_num

164 LOCAL remove_not_digit, ok_AE_0, ok_digit, not_cr

165 

166 ; protect from wrong definition location:

167 JMP     skip_proc_scan_num

168 

169 SCAN_NUM        PROC    NEAR

170         PUSH    DX

171         PUSH    AX

172         PUSH    SI

173         

174         MOV     CX, 0

175 

176         ; reset flag:

177         MOV     CS:make_minus, 0

178 

179 next_digit:

180 

181         ; get char from keyboard

182         ; into AL:

183         MOV     AH, 00h

184         INT     16h

185         ; and print it:

186         MOV     AH, 0Eh

187         INT     10h

188 

189         ; check for MINUS:

190         CMP     AL, '-'

191         JE      set_minus

192 

193         ; check for ENTER key:

194         CMP     AL, 13  ; carriage return?

195         JNE     not_cr

196         JMP     stop_input

197 not_cr:

198 

199 

200         CMP     AL, 8                   ; 'BACKSPACE' pressed?

201         JNE     backspace_checked

202         MOV     DX, 0                   ; remove last digit by

203         MOV     AX, CX                  ; division:

204         DIV     CS:ten                  ; AX = DX:AX / 10 (DX-rem).

205         MOV     CX, AX

206         PUTC    ' '                     ; clear position.

207         PUTC    8                       ; backspace again.

208         JMP     next_digit

209 backspace_checked:

210 

211 

212         ; allow only digits:

213         CMP     AL, '0'

214         JAE     ok_AE_0

215         JMP     remove_not_digit

216 ok_AE_0:        

217         CMP     AL, '9'

218         JBE     ok_digit

219 remove_not_digit:       

220         PUTC    8       ; backspace.

221         PUTC    ' '     ; clear last entered not digit.

222         PUTC    8       ; backspace again.        

223         JMP     next_digit ; wait for next input.       

224 ok_digit:

225 

226 

227         ; multiply CX by 10 (first time the result is zero)

228         PUSH    AX

229         MOV     AX, CX

230         MUL     CS:ten                  ; DX:AX = AX*10

231         MOV     CX, AX

232         POP     AX

233 

234         ; check if the number is too big

235         ; (result should be 16 bits)

236         CMP     DX, 0

237         JNE     too_big

238 

239         ; convert from ASCII code:

240         SUB     AL, 30h

241 

242         ; add AL to CX:

243         MOV     AH, 0

244         MOV     DX, CX      ; backup, in case the result will be too big.

245         ADD     CX, AX

246         JC      too_big2    ; jump if the number is too big.

247 

248         JMP     next_digit

249 

250 set_minus:

251         MOV     CS:make_minus, 1

252         JMP     next_digit

253 

254 too_big2:

255         MOV     CX, DX      ; restore the backuped value before add.

256         MOV     DX, 0       ; DX was zero before backup!

257 too_big:

258         MOV     AX, CX

259         DIV     CS:ten  ; reverse last DX:AX = AX*10, make AX = DX:AX / 10

260         MOV     CX, AX

261         PUTC    8       ; backspace.

262         PUTC    ' '     ; clear last entered digit.

263         PUTC    8       ; backspace again.        

264         JMP     next_digit ; wait for Enter/Backspace.

265         

266         

267 stop_input:

268         ; check flag:

269         CMP     CS:make_minus, 0

270         JE      not_minus

271         NEG     CX

272 not_minus:

273 

274         POP     SI

275         POP     AX

276         POP     DX

277         RET

278 make_minus      DB      ?       ; used as a flag.

279 ten             DW      10      ; used as multiplier.

280 SCAN_NUM        ENDP

281 

282 skip_proc_scan_num:

283 

284 DEFINE_SCAN_NUM         ENDM

285 ;***************************************************************

286 

287 

288 ;***************************************************************

289 ; this macro defines a procedure to print a null terminated

290 ; string at current cursor position, receives address of string in DS:SI

291 DEFINE_PRINT_STRING     MACRO

292 LOCAL   next_char, printed, skip_proc_print_string

293 

294 ; protect from wrong definition location:

295 JMP     skip_proc_print_string

296 

297 PRINT_STRING PROC NEAR

298 PUSH    AX      ; store registers...

299 PUSH    SI      ;

300 

301 next_char:      

302         MOV     AL, [SI]

303         CMP     AL, 0

304         JZ      printed

305         INC     SI

306         MOV     AH, 0Eh ; teletype function.

307         INT     10h

308         JMP     next_char

309 printed:

310 

311 POP     SI      ; re-store registers...

312 POP     AX      ;

313 

314 RET

315 PRINT_STRING ENDP

316 

317 skip_proc_print_string:

318 

319 DEFINE_PRINT_STRING     ENDM

320 ;***************************************************************

321 

322 

323 ;***************************************************************

324 ; This macro defines a procedure to print a null terminated

325 ; string at current cursor position.

326 ; The ZERO TERMINATED string should be defined just after the CALL. For example:

327 ;

328 ; CALL PTHIS

329 ; db 'Hello World!', 0

330 ;

331 ; Address of string is stored in the Stack as return address.

332 ; Procedure updates value in the Stack to make return

333 ; after string definition.

334 DEFINE_PTHIS     MACRO

335 LOCAL   next_char, printed, skip_proc_pthis, temp1

336 

337 ; protect from wrong definition location:

338 JMP     skip_proc_pthis

339 

340 PTHIS PROC NEAR

341 

342 MOV     CS:temp1, SI  ; store SI register.

343 

344 POP     SI            ; get return address (IP).

345 

346 PUSH    AX            ; store AX register.

347 

348 next_char:      

349         MOV     AL, CS:[SI]

350         INC     SI            ; next byte.

351         CMP     AL, 0

352         JZ      printed        

353         MOV     AH, 0Eh       ; teletype function.

354         INT     10h

355         JMP     next_char     ; loop.

356 printed:

357 

358 POP     AX            ; re-store AX register.

359 

360 ; SI should point to next command after

361 ; the CALL instruction and string definition:

362 PUSH    SI            ; save new return address into the Stack.

363 

364 MOV     SI, CS:temp1  ; re-store SI register.

365 

366 RET

367 temp1  DW  ?    ; variable to store original value of SI register.

368 PTHIS ENDP

369 

370 skip_proc_pthis:

371 

372 DEFINE_PTHIS     ENDM

373 ;***************************************************************

374 

375 

376 ;***************************************************************

377 ; This macro defines a procedure to get a null terminated

378 ; string from user, the received string is written to buffer

379 ; at DS:DI, buffer size should be in DX.

380 ; Procedure stops the input when 'Enter' is pressed.

381 DEFINE_GET_STRING       MACRO

382 LOCAL   empty_buffer, wait_for_key, skip_proc_get_string

383 LOCAL   exit, add_to_buffer

384 

385 ; protect from wrong definition location:

386 JMP     skip_proc_get_string

387 

388 GET_STRING      PROC    NEAR

389 PUSH    AX

390 PUSH    CX

391 PUSH    DI

392 PUSH    DX

393 

394 MOV     CX, 0                   ; char counter.

395 

396 CMP     DX, 1                   ; buffer too small?

397 JBE     empty_buffer            ;

398 

399 DEC     DX                      ; reserve space for last zero.

400 

401 

402 ;============================

403 ; loop to get and processes key presses:

404 

405 wait_for_key:

406 

407 MOV     AH, 0                   ; get pressed key.

408 INT     16h

409 

410 CMP     AL, 13                  ; 'RETURN' pressed?

411 JZ      exit

412 

413 

414 CMP     AL, 8                   ; 'BACKSPACE' pressed?

415 JNE     add_to_buffer

416 JCXZ    wait_for_key            ; nothing to remove!

417 DEC     CX

418 DEC     DI

419 PUTC    8                       ; backspace.

420 PUTC    ' '                     ; clear position.

421 PUTC    8                       ; backspace again.

422 JMP     wait_for_key

423 

424 add_to_buffer:

425 

426         CMP     CX, DX          ; buffer is full?

427         JAE     wait_for_key    ; if so wait for 'BACKSPACE' or 'RETURN'...

428 

429         MOV     [DI], AL

430         INC     DI

431         INC     CX

432         

433         ; print the key:

434         MOV     AH, 0Eh

435         INT     10h

436 

437 JMP     wait_for_key

438 ;============================

439 

440 exit:

441 

442 ; terminate by null:

443 MOV     [DI], 0

444 

445 empty_buffer:

446 

447 POP     DX

448 POP     DI

449 POP     CX

450 POP     AX

451 RET

452 GET_STRING      ENDP

453 

454 

455 skip_proc_get_string:

456 

457 DEFINE_GET_STRING       ENDM

458 ;***************************************************************

459 

460 ;***************************************************************

461 ; this macro defines procedure to clear the screen,

462 ; (done by scrolling entire screen window),

463 ; and set cursor position to top of it:

464 DEFINE_CLEAR_SCREEN     MACRO

465 LOCAL skip_proc_clear_screen

466 

467 ; protect from wrong definition location:

468 JMP     skip_proc_clear_screen

469 

470 CLEAR_SCREEN PROC NEAR

471         PUSH    AX      ; store registers...

472         PUSH    DS      ;

473         PUSH    BX      ;

474         PUSH    CX      ;

475         PUSH    DI      ;

476 

477         MOV     AX, 40h

478         MOV     DS, AX  ; for getting screen parameters.

479         MOV     AH, 06h ; scroll up function id.

480         MOV     AL, 0   ; scroll all lines!

481         MOV     BH, 07  ; attribute for new lines.

482         MOV     CH, 0   ; upper row.

483         MOV     CL, 0   ; upper col.

484         MOV     DI, 84h ; rows on screen -1,

485         MOV     DH, [DI] ; lower row (byte).

486         MOV     DI, 4Ah ; columns on screen,

487         MOV     DL, [DI]

488         DEC     DL      ; lower col.

489         INT     10h

490 

491         ; set cursor position to top

492         ; of the screen:

493         MOV     BH, 0   ; current page.

494         MOV     DL, 0   ; col.

495         MOV     DH, 0   ; row.

496         MOV     AH, 02

497         INT     10h

498 

499         POP     DI      ; re-store registers...

500         POP     CX      ;

501         POP     BX      ;

502         POP     DS      ;

503         POP     AX      ;

504 

505         RET

506 CLEAR_SCREEN ENDP

507 

508 skip_proc_clear_screen:

509 

510 DEFINE_CLEAR_SCREEN     ENDM

511 ;***************************************************************

512 

513 

514 ;***************************************************************

515 

516 ; This macro defines a procedure that prints number in AX,

517 ; used with PRINT_NUM_UNS to print signed numbers:

518 ; Requires DEFINE_PRINT_NUM_UNS !!!

519 DEFINE_PRINT_NUM        MACRO

520 LOCAL not_zero, positive, printed, skip_proc_print_num

521 

522 ; protect from wrong definition location:

523 JMP     skip_proc_print_num

524 

525 PRINT_NUM       PROC    NEAR

526         PUSH    DX

527         PUSH    AX

528 

529         CMP     AX, 0

530         JNZ     not_zero

531 

532         PUTC    '0'

533         JMP     printed

534 

535 not_zero:

536         ; the check SIGN of AX,

537         ; make absolute if it's negative:

538         CMP     AX, 0

539         JNS     positive

540         NEG     AX

541 

542         PUTC    '-'

543 

544 positive:

545         CALL    PRINT_NUM_UNS

546 printed:

547         POP     AX

548         POP     DX

549         RET

550 PRINT_NUM       ENDP

551 

552 skip_proc_print_num:

553 

554 DEFINE_PRINT_NUM        ENDM

555 

556 ;***************************************************************

557 

558 ; This macro defines a procedure that prints out an unsigned

559 ; number in AX (not just a single digit)

560 ; allowed values from 0 to 65535 (0FFFFh)

561 DEFINE_PRINT_NUM_UNS    MACRO

562 LOCAL begin_print, calc, skip, print_zero, end_print, ten

563 LOCAL skip_proc_print_num_uns

564 

565 ; protect from wrong definition location:

566 JMP     skip_proc_print_num_uns

567 

568 PRINT_NUM_UNS   PROC    NEAR

569         PUSH    AX

570         PUSH    BX

571         PUSH    CX

572         PUSH    DX

573 

574         ; flag to prevent printing zeros before number:

575         MOV     CX, 1

576 

577         ; (result of "/ 10000" is always less or equal to 9).

578         MOV     BX, 10000       ; 2710h - divider.

579 

580         ; AX is zero?

581         CMP     AX, 0

582         JZ      print_zero

583 

584 begin_print:

585 

586         ; check divider (if zero go to end_print):

587         CMP     BX,0

588         JZ      end_print

589 

590         ; avoid printing zeros before number:

591         CMP     CX, 0

592         JE      calc

593         ; if AX<BX then result of DIV will be zero:

594         CMP     AX, BX

595         JB      skip

596 calc:

597         MOV     CX, 0   ; set flag.

598 

599         MOV     DX, 0

600         DIV     BX      ; AX = DX:AX / BX   (DX=remainder).

601 

602         ; print last digit

603         ; AH is always ZERO, so it's ignored

604         ADD     AL, 30h    ; convert to ASCII code.

605         PUTC    AL

606 

607 

608         MOV     AX, DX  ; get remainder from last div.

609 

610 skip:

611         ; calculate BX=BX/10

612         PUSH    AX

613         MOV     DX, 0

614         MOV     AX, BX

615         DIV     CS:ten  ; AX = DX:AX / 10   (DX=remainder).

616         MOV     BX, AX

617         POP     AX

618 

619         JMP     begin_print

620         

621 print_zero:

622         PUTC    '0'

623         

624 end_print:

625 

626         POP     DX

627         POP     CX

628         POP     BX

629         POP     AX

630         RET

631 ten             DW      10      ; used as divider.      

632 PRINT_NUM_UNS   ENDP

633 

634 skip_proc_print_num_uns:

635 

636 DEFINE_PRINT_NUM_UNS    ENDM

637 ;***************************************************************

638 

639 

640 

                                                                                                                                                                                                             

 

<<< 上一部分 <<<【8086汇编基础】04--中断

>>> 下一部分 >>>【8086汇编基础】06--算术运算与逻辑指令

 

你可能感兴趣的:(常用函数)