LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
12
返回列表 发新帖
楼主: home_king

如何实现汇编级的非阻塞I/O

[复制链接]
 楼主| 发表于 2005-1-11 19:30:50 | 显示全部楼层
今天在整理旧资料,发现以前编写了一个windows下的串口通讯程序minicom,我想就发出来大家参考一下吧,虽然事隔已久,而且是windows版本,但姑且看看它的原理吧。
使用IBMx86汇编语言编写,实现的功能是串口的聊天通讯,工作在全双工非阻塞模式,可以使用特殊控制字符来清屏、退出,扩展性较好。

  1. TITLE Serial HyperCom v0.01 (EXE)

  2. ;Written by home_king

  3. ;home_king@163.com

  4. ;Macro to receive/send byte through COM1 port series.
  5. MOUTB        MACRO        OADDR,        OBYTE
  6.         MOV        DX,        OADDR
  7.         MOV        AL,        OBYTE
  8.         OUT        DX,        AL
  9.         ENDM
  10.        
  11. MINB        MACRO        IADDR
  12.         MOV        DX,        IADDR
  13.         IN        AL,        DX
  14.         ENDM
  15.        
  16. ;Macro to do comparison between two strings.
  17. CMPSTR        MACRO        STR_LEN, STR1, STR2
  18.         MOV        CX,        STR_LEN
  19.         LEA        DI,        STR1
  20.         LEA        SI,        STR2
  21.         REPE        CMPSB
  22.         ENDM

  23. ;Macro to clear the specified region of the screen.
  24. CLRSCR        MACRO        CLRROWS, STARTROW, STARTCOL, ENDROW, ENDCOL, ATTRIB
  25.         MOV        AH,        06H
  26.         MOV        AL,        CLRROWS
  27.         MOV        BH,        ATTRIB
  28.         MOV        CH,        STARTROW
  29.         MOV        CL,        STARTCOL
  30.         MOV        DH,        ENDROW
  31.         MOV        DL,        ENDCOL       
  32.         INT        10H
  33.         ENDM

  34. ;Macro for COM1 Initialization
  35. COMINIT        MACRO       
  36.         ;set baud rate 2400
  37.         ;Enable set Baud rate
  38.         MOUTB        COMBASEADDR+3,        10000000B
  39.         MOUTB        COMBASEADDR,        30H
  40.         ;enable receive interrupt
  41.         MOUTB        COMBASEADDR+1,        00000001B
  42.         ;8 data bits, 1 stop bit, no Parity check
  43.         MOUTB        COMBASEADDR+3,        00000011B
  44.         ENDM

  45. ;Macro to locate cursor.
  46. LOCATECURSOR        MACRO        CURSORROW, CURSORCOL
  47.         MOV        AH,        02H
  48.         MOV         BH,        00
  49.         MOV        DH,        CURSORROW
  50.         MOV        DL,        CURSORCOL
  51.         INT        10H
  52.         ENDM
  53.        
  54. MSHOWSTR        MACRO        ATTRIB,        STRLEN,        SHOWROW
  55.         MOV        AH,        13H
  56.         MOV        AL,        01
  57.         MOV        BH,        00
  58.         MOV        BL,        ATTRIB
  59.         MOV        CX,        STRLEN
  60.         MOV        DH,        SHOWROW
  61.         MOV        DL,        01
  62.         INT        10H       
  63.         ENDM
  64.        
  65. SHOWPROMPT        MACRO        PROMPT, CURSORROW
  66.         LEA        BP,        PROMPT
  67.         CALL        GETLEN
  68.         MSHOWSTR        6AH, STRLEN, CURSORROW
  69.         ENDM

  70. ;------------------------------------------
  71.         .MODEL SMALL
  72.         .STACK 64
  73. ;------------------------------------------
  74.         .DATA
  75. ;Buffer Chars
  76. ;used to flag
  77. BUFCHAR        EQU        '$'
  78. ENDCHAR        EQU        '#'

  79. ;Key Defination
  80. KRETURN        EQU        0DH
  81. KBACK        EQU        08H
  82. KBLANK        EQU        00H
  83. KTAB        EQU        09H

  84. ;Buffer Defination
  85. MAXLEN                EQU        78
  86. INPUTBUF        DB        MAXLEN dup(BUFCHAR)
  87. REVBUF                DB        MAXLEN+1 dup(BUFCHAR)

  88. ;Cursor Location Trace
  89. CURSORROW        DB        23
  90. CURSORCOL        DB        00
  91. SHOWROW                DB        SHOWTOP-1
  92. SHOWTOP                EQU        05
  93. SHOWEDGE        EQU        19

  94. ;COM1 I/O port.
  95. COMBASEADDR        EQU        03F8H

  96. ;Color Attribute
  97. ATTRIB                DB        ?
  98. REVATTRIB        EQU        84H
  99. KEYATTRIB        EQU        8AH
  100. INPUTATTRIB        EQU        6FH
  101. SHOWBACKGROUND        EQU        80H

  102. ;Flag Variable
  103. COMMONFLAG        DB        00

  104. ;Variable to store the length of a string
  105. STRLEN        DW        ?

  106. CHARREG        DB        ?
  107. ENDPOS        DW        ?

  108. ;Miscellaneous variables
  109. BANNER        DB        '***HyperCom v0.01*** (home_king@163.com)','$'
  110. PROMPT        DB        '[*HyperCom@SCAU*]:','$'
  111. PROMPTLEN        DW        ?

  112. ;Special Key Function
  113. STRQUIT                db        '/q'
  114. STRRESET        db        '/r'

  115. ;------------------------------------------
  116.         .386
  117.         .CODE
  118. START        PROC        FAR
  119.         MOV        AX, @data
  120.         MOV        DS, AX
  121.         MOV        ES, AX
  122.        
  123.         ;clear the screen
  124.         clrscr        00, 00, 00, CURSORROW, 79, 00
  125.         clrscr        01, CURSORROW, 01, CURSORROW, 78, 6FH
  126.         clrscr        SHOWEDGE-SHOWTOP+1, SHOWTOP, 01, showedge, 78, SHOWBACKGROUND
  127.        
  128.         ;Initialize COM1
  129.         COMINIT
  130.        
  131.         ;show banner
  132.         lea        bp,        banner
  133.         call        GETLEN
  134.         ;show adjust
  135.         MOV        AX,        80
  136.         SUB        AX,        STRLEN
  137.         SHR        AX,        2
  138.         MOV        DL,        AL
  139.         MOV        AH,        13H
  140.         MOV        AL,        01
  141.         MOV        BH,        00
  142.         MOV        BL,        0eh
  143.         MOV        CX,        STRLEN
  144.         MOV        DH,        00
  145.         INT        10H
  146.        
  147.         LEA        SI,        INPUTBUF
  148.        
  149.         ;show prompt
  150.         PUSH        SI
  151.         SHOWPROMPT        PROMPT,        CURSORROW
  152.         ;Insert ENDCHAR
  153.         MOV        AX,        MAXLEN
  154.         SUB        AX,        STRLEN
  155.         ADD        SI,        AX
  156.         MOV        BYTE PTR [SI],        ENDCHAR
  157.         MOV        ENDPOS,        SI
  158.         ;Save PROMPT's length and adjust CURSORCOL
  159.         MOV        AX,        STRLEN
  160.         INC        AX
  161.         MOV        PROMPTLEN,        AX
  162.         MOV        CURSORCOL,        AL
  163.         POP        SI
  164.        
  165.         ;Initial cursor position
  166.         LOCATECURSOR        CURSORROW,        CURSORCOL
  167.        
  168.         ;***Engine Start***
  169.         ;check input status
  170. CHECKINPUT:
  171.         MOV        AH,        11H
  172.         INT        16H
  173.         JNZ        INPUT

  174.         ;check receive status
  175. CHECKREV:
  176.         ;test start
  177.         ;LEA        BP,        PROMPT
  178.         ;CALL        GETLEN
  179.         ;MSHOWSTR        REVATTRIB, STRLEN, 15
  180.         ;test end
  181.        
  182.         MINB        COMBASEADDR +5
  183.         TEST        AL,        00000001B
  184.         JZ        CHECKINPUT
  185.         CALL        REVHANDLER
  186.         JMP        CHECKINPUT
  187.         ;***Engine End***

  188. INPUT:
  189.         ;check whether the buffer is overflow or not
  190.         CMP        BYTE PTR [SI],        ENDCHAR       
  191.         JE        GOSHOW

  192.         MOV        COMMONFLAG,        00
  193.         MOV        AH,        10H
  194.         INT        16H
  195.         MOV        CHARREG,        AL

  196.         ;***special key parsing start***
  197.        
  198.         ;check 'RETURN' key
  199.         cmp        CHARREG,        KRETURN
  200.         je        goshow

  201.         ;check 'BLACKSPACE' key
  202. CHKBCK:
  203.         CMP        CHARREG,        KBACK
  204.         JNE        CHKTAB
  205.         CMP        BYTE PTR inputbuf,        BUFCHAR
  206.         JE        input
  207.         ;fill '$'
  208.         MOV        BYTE PTR [SI],        BUFCHAR
  209.         dec        si
  210.         ;set flag
  211.         mov        commonflag,        BUFCHAR
  212.         ;fill '$' too
  213.         MOV        BYTE PTR [SI],        BUFCHAR
  214.         mov        ATTRIB,        66H
  215.         ;process back
  216.         dec        cursorcol
  217.         LOCATECURSOR        CURSORROW,        CURSORCOL
  218.         jmp        goecho
  219. CHKTAB:
  220.         ;check 'TAB' key
  221.         cmp        CHARREG,        KTAB
  222.         JNE        normalchar
  223.         ;fill pads=blank*(8-((CURSORCOL+1) mod 8))
  224.         ;setcursor pads+1
  225.         MOV        AL,        CURSORCOL
  226.         AND        AX,        0FH
  227.         INC        AX
  228.         MOV        CX,        08
  229.         DIV        CL
  230.         AND        AX,        0FF00H
  231.         XCHG        AL,        AH
  232.         SUB        CX,        AX
  233.         MOV        STRLEN,        CX
  234. DOTAB1:
  235.         CMP        CX,        00
  236.         JE        DOTAB2
  237.         MOV        BYTE PTR [SI],        KBLANK
  238.         INC        SI
  239.         DEC        CX
  240.         JMP        DOTAB1
  241. DOTAB2:
  242.         MOV        COMMONFLAG,        KTAB
  243.         MOV        AL,        KBLANK
  244.         MOV        ATTRIB,        INPUTATTRIB
  245.         JMP        GOECHO
  246.        
  247.         ;***special key parsing end***
  248.        
  249. normalchar:
  250.         MOV        AL,        CHARREG
  251.         mov        byte ptr [si],        AL
  252.         inc        si
  253.         mov        ATTRIB,        INPUTATTRIB
  254. goecho:
  255.         mov        ah,        09h
  256.         mov        bh,        00
  257.         mov        bl,        ATTRIB
  258.         mov        cx,        1
  259.         int        10h       
  260. endecho:
  261.         CMP        commonflag,        BUFCHAR
  262.         je        input
  263.         CMP        COMMONFLAG,        KTAB
  264.         JNE        ENDECHO1
  265.         DEC        STRLEN
  266.         CMP        STRLEN,        00
  267.         JE        ENDECHO1       
  268.         INC        CURSORCOL
  269.         LOCATECURSOR        CURSORROW,        CURSORCOL
  270.         JMP        GOECHO
  271. ENDECHO1:
  272.         inc        cursorcol
  273.         LOCATECURSOR        CURSORROW,        CURSORCOL
  274.         jmp        CHECKINPUT
  275. goshow:       
  276.         ;fill '$'
  277.         mov        byte ptr [si],        BUFCHAR
  278.         cmp        byte ptr inputbuf,        BUFCHAR
  279.         je        restart

  280.         ;send strings
  281.         CALL        SEND

  282.         ;show strings
  283.         lea        bp,        inputbuf
  284.         call        GETLEN

  285.         ;***command process start***
  286.         cmpstr        strlen, inputbuf, strquit
  287.         JE        normalquit
  288.         cmpstr        strlen, inputbuf, strreset
  289.         JE        clrshow
  290.         ;***command process end***

  291.         lea        bp,        inputbuf
  292.         mov        ATTRIB,        KEYATTRIB
  293.         CALL        SHOWSTR
  294.        
  295. goshow1:
  296.         lea        si,        inputbuf
  297. restart:
  298.         ;clear the input region
  299.         clrscr        01, 17h, 01, 17h, 4eh, 6FH

  300.         ;redraw PROMPT
  301.         SHOWPROMPT        PROMPT,        CURSORROW
  302.        
  303.         ;fill '#'
  304.         mov        byte ptr inputbuf,        BUFCHAR
  305.         ;fill ENDCHAR
  306.         PUSH        SI
  307.         LEA        SI,        INPUTBUF
  308.         MOV        SI,        ENDPOS
  309.         mov        byte ptr [SI],        ENDCHAR
  310.         POP        SI
  311.        
  312.         MOV        AX,        PROMPTLEN
  313.         mov        cursorcol,        AL
  314.         LOCATECURSOR        CURSORROW,        CURSORCOL
  315.         jmp        CHECKINPUT
  316. normalquit:
  317.         clrscr        00, 00, 00, 18h, 4fh, 00
  318.         mov        ax,        4c00h
  319.         int        21h
  320. clrshow:
  321.         clrscr        SHOWEDGE-SHOWTOP+1, SHOWTOP, 01, showedge, 78, SHOWBACKGROUND
  322.         mov        showrow,        SHOWTOP-1
  323.         jmp        goshow1
  324. START        ENDP
  325.        

  326. REVHANDLER        PROC        NEAR
  327.         PUSHA
  328.         ;receive strings
  329.         CALL        RECEIVE
  330.         ;show strings
  331.         LEA        BP,        REVBUF
  332.         MOV        ATTRIB,        REVATTRIB
  333.         CALL        SHOWSTR
  334.         ;reset cursor
  335.         LOCATECURSOR        CURSORROW,        CURSORCOL
  336.         POPA
  337.         RET
  338. REVHANDLER        ENDP

  339. ;Send routine
  340. SEND        PROC        NEAR
  341.         PUSHA
  342.         LEA        SI,        inputbuf
  343. CHECKTXD:
  344.         MINB        COMBASEADDR +5
  345.         TEST        AL,        20H
  346.         JZ        CHECKTXD
  347.         MOV        AL,                [SI]
  348.         MOUTB        COMBASEADDR,        AL
  349.         INC        SI
  350.         CMP        BYTE PTR [SI],        BUFCHAR
  351.         JNE        CHECKTXD
  352.         MOUTB        COMBASEADDR,        BUFCHAR
  353.         POPA
  354.         RET
  355. SEND        ENDP

  356. ;receive routine
  357. RECEIVE        PROC        NEAR
  358.         PUSHA
  359.         LEA        DI,        REVBUF
  360. CHECKRXD:
  361.         MINB        COMBASEADDR +5
  362.         TEST        AL,        01
  363.         JZ        CHECKRXD
  364.         MINB        COMBASEADDR
  365.         MOV        BYTE PTR [DI],        AL
  366.         INC        DI
  367.         CMP        AL,        BUFCHAR
  368.         JNE        CHECKRXD
  369.         POPA
  370.         RET
  371. RECEIVE        ENDP

  372. GETLEN        PROC        NEAR
  373.         PUSHA
  374.         MOV        SI,        BP
  375.         MOV        CX,        00
  376. DOGET:
  377.         INC        CX
  378.         INC        SI
  379.         CMP        BYTE PTR [SI],        BUFCHAR
  380.         JNE        DOGET
  381.         MOV        STRLEN,        CX
  382.         POPA
  383.         RET
  384. GETLEN        ENDP

  385. SHOWSTR        PROC        NEAR
  386.         PUSHA
  387. PRESHOW:
  388.         CMP        SHOWROW,        showedge
  389.         JB        showentry
  390.         clrscr        01, SHOWTOP+1, 01, showedge, 78, SHOWBACKGROUND
  391.         jmp        doshow
  392. showentry:
  393.         inc        SHOWROW
  394. doshow:
  395.         MSHOWSTR        ATTRIB,        STRLEN,        SHOWROW
  396.         POPA
  397.         RET
  398. SHOWSTR        ENDP
  399.         END        START
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
发表于 2005-1-12 08:59:58 | 显示全部楼层
Post by home_king
思考了许久,还是不得其解。
给出三个汇编级串口编程的高级话题,考考大家。

1.究竟如何获知各类外设控制芯片的端口地址(除了查设备手册)呢?

2.BIOS利用x86架构的INT n提供的串口中断究竟与INTR外部串口中断有什么关联呢?我思考并多番实践过,两者的功能几乎等价。(可惜,后者我采用查询方式来"仿真"中断的并行效果,目前我还想不出如何利用INTR实现外部中断处理,请看第3问)

3.进一步,我如何编写我自己的串口中断服务程序呢?关键在于如何与INTR在中断服务程序的入口地址方面达成共识,也就是说,如何注册INT n。某教科书上曾提及过这话题,但并不详细,只是假设串口中断服务程序的入口地址为已知。奇怪。


1 端口地址是硬件设计时决定的(仅对于这些传统设备),除了查手册,那就是看电路原理图了。

2 汇编中的“INT n”  和 INTR中断输入 本质上没什么关系,前者叫软中断(这个名字几乎是误导),后者叫硬中断,都用中断向量表定位程序,但功能上完全不同。前者是BIOS或DOS提供的系统调用接口(对应的中断向量表项所指向的程序是实现一些底层功能的程序),后者是硬件事件的通知(对应的中断向量表所指向的程序是对这一事件的响应程序)。

3 在DOS下编写中断服务程序很容易,编好服务程序-〉驻留内存-〉设置中断向量表项,DOS提供了实现这些功能的系统调用。参考汇编语言教材和微机接口与通信教材。

4 我觉得你这个需求不需要写中断服务程序。在汇编级,“阻塞”就是循环检查串口状态寄存器,可读写则读写,否则就死等;“非阻塞”就是检查一次串口状态寄存器,可读写则读写,否则去做别的事。因此,你只需要让主程序是一个大循环,串口操作和你要做的其它事都在这同一个循环当中,并且使用上述的“非阻塞”方式即可。
 楼主| 发表于 2005-1-12 09:47:50 | 显示全部楼层
Post by doubleelec
1 端口地址是硬件设计时决定的(仅对于这些传统设备),除了查手册,那就是看电路原理图了。

2 汇编中的“INT n”  和 INTR中断输入 本质上没什么关系,前者叫软中断(这个名字几乎是误导),后者叫硬中断,都用中断向量表定位程序,但功能上完全不同。前者是BIOS或DOS提供的系统调用接口(对应的中断向量表项所指向的程序是实现一些底层功能的程序),后者是硬件事件的通知(对应的中断向量表所指向的程序是对这一事件的响应程序)。

3 在DOS下编写中断服务程序很容易,编好服务程序-〉驻留内存-〉设置中断向量表项,DOS提供了实现这些功能的系统调用。参考汇编语言教材和微机接口与通信教材。

4 我觉得你这个需求不需要写中断服务程序。在汇编级,“阻塞”就是循环检查串口状态寄存器,可读写则读写,否则就死等;“非阻塞”就是检查一次串口状态寄存器,可读写则读写,否则去做别的事。因此,你只需要让主程序是一个大循环,串口操作和你要做的其它事都在这同一个循环当中,并且使用上述的“非阻塞”方式即可。

1.对于端口地址,理论上说就是老兄您说的方法,但实际上并不能使用这些方法,你有你买的PC机给与的CPU手册吗?没有。你有电路原理图吗?Intel不会轻易给最终用户。所以旧架构可以参阅Intel的specification,但新架构如Prescott等就无从入手了。

我对于IBM宏汇编并不大精通,兄弟可以看看我的程序,给一些意见吗?(虽然是N久之前的作品)
发表于 2005-1-12 12:09:50 | 显示全部楼层
串口、并口的端口地址和CPU没关系,是由主板决定的,这些地址与以前的IBM PC一般是兼容的。你看到的某些旧资料上的信息仍然有效
 楼主| 发表于 2005-1-12 14:09:31 | 显示全部楼层
Post by doubleelec
串口、并口的端口地址和CPU没关系,是由主板决定的,这些地址与以前的IBM PC一般是兼容的。你看到的某些旧资料上的信息仍然有效

就这些资料也是很难很难找的。
比如说串口的若干个控制字寄存器的资料。我找了N天才在某bbs上找到一份完整的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表