-1

私が取り組んでいる(宿題用の)単純なプログラムでは、入力としてキーストロークを取得し、それが該当するカテゴリを返す必要があります(印刷可能な文字、小数などです..)

cmp を使用して、キーストロークをそのカテゴリの最大値および/または最小値の値と比較しています (たとえば、キーストロークの ASCII コードが 0x7F を超える場合、それは印刷可能な文字です)

ただし、何があっても、つまり、エスケープボタンを入力として使用すると、「コントロールキー」が出力されないため、私の比較では明らかに機能していないものがあります。

ASCII 値に基づいて比較する前に、キーをさらに処理する必要があるのでしょうか?

これが私のコードです

  segment .data
    controlKey: db "Control Key", 10
    controlLen: equ $-controlKey

    printableKey: db "Printable", 10
    printableLen: equ $-printableKey

    decimalKey: db "Decimal", 10
    decimalLen: equ $-decimalKey

segment .bss

    key resb 2

segment .text

    global main
main:
    mov eax, 3  ; system call 3 to get input
    mov ebx, 0  ; standart input device
    mov ecx, key    ; pointer to id
    mov edx, 2  ; take in this many bytes
    int 0x80    

control:        ; check if it's a control key
    mov ebx, 31 ; highest control key
    mov edx, key
    cmp edx, ebx
    jg  printable
    mov eax, 4
    mov ebx, 1
    mov ecx, controlKey
    mov edx, controlLen
    int 0x80
    ; jmp exit  ; It's obviously not any of the other categories

printable:  ; Tell that it's a printable symbol
    mov eax, 4
    mov ebx, 1
    mov ecx, printableKey
    mov edx, printableLen
    int 0x80
decimal: 
    mov ebx, 30h    ; smallest decimal ASCII 
    mov edx, key
    cmp edx, ebx
    jl  uppercase
    mov ebx, 39h    ; test against 9
    cmp edx, ebx
    jg  uppercase
    mov eax, 4
    mov ebx, 1
    mov ecx, decimalKey
    mov edx, decimalLen
    int 0x80

uppercase:  
lowercase:



    mov eax, 4  ; system call 4 for output
    mov ebx, 1  ; standard output device
    mov ecx, key    ; move the content into ecx
    mov edx, 1  ; tell edx how many bytes
    int 0x80    ;

exit:
    mov eax, 1
    xor ebx, ebx
    int 0x80
4

2 に答える 2

0

Escキーは、アプリケーションが実行されている端末によって(おそらく)キャッチされているため、アプリケーションによって読み取られません。コードでsyscallを使用していることがわかります。readもちろん、これは問題ありません。ただし、この関数はファイル記述子からの読み取りのみを提供することを覚えておく必要があります。ファイル記述子には、キーボードから送信されるすべての制御信号が含まれている必要はありません。ファイルは標準入力としてプロセスにリダイレクトされる可能性があるため、ファイル記述子()はキーボードから取得する必要はありませstdin

Linuxのシステムコールだけでやろうとしていることを達成するための良い方法があるかどうかはわかりません(キーストロークが表すデータではなく、キーストロークをキャプチャします。これが現在行っていることです)。たとえば、またはなどの端末制御ライブラリを使用してみることができますが、それはあなたの割り当ての一部ではないと思います。ncursestermios

于 2013-02-28T23:05:25.863 に答える
0

しばらく前にこれを行いました。これは、文字エコーのオン/オフ、および正規モードのオン/オフを切り替える方法を示すサンプルです。実行すると、キーを押すとキーコードが画面に表示され、shift+q が押されるとプログラムが終了します。

terminos.asm

ICANON      equ 1<<1
ECHO        equ 1<<3

sys_exit    equ 1
sys_read    equ 3
sys_write   equ 4
stdin       equ 0
stdout      equ 1


global _start

SECTION     .bss
lpBufIn     resb    2
lpBufOut    resb    2
termios     resb 36 

section .text
_start:
    call    echo_off
    call    canonical_off 

.GetCode:    
    call    GetKeyCode
    movzx   esi, byte[lpBufIn]
    push    esi
    call    PrintNum
    pop     esi
    cmp     esi, 81
    jne     .GetCode

    call    echo_on
    call    canonical_on

    mov     eax, sys_exit
    xor     ebx, ebx
    int     80H

;~ #########################################
GetKeyCode: 
    mov     eax, sys_read
    mov     ebx, stdin
    mov     ecx, lpBufIn
    mov     edx, 1
    int     80h
    ret

;~ #########################################
canonical_off:
        call read_stdin_termios

        ; clear canonical bit in local mode flags
        mov eax, ICANON
        not eax
        and [termios+12], eax

        call write_stdin_termios
        ret

;~ #########################################
echo_off:
        call read_stdin_termios

        ; clear echo bit in local mode flags
        mov eax, ECHO
        not eax
        and [termios+12], eax

        call write_stdin_termios
        ret

;~ #########################################
canonical_on:
        call read_stdin_termios

        ; set canonical bit in local mode flags
        or dword [termios+12], ICANON

        call write_stdin_termios
        ret

;~ #########################################
echo_on:
        call read_stdin_termios

        ; set echo bit in local mode flags
        or dword [termios+12], ECHO

        call write_stdin_termios
        ret

;~ #########################################
read_stdin_termios:
        mov eax, 36h
        mov ebx, stdin
        mov ecx, 5401h
        mov edx, termios
        int 80h
        ret

;~ #########################################
write_stdin_termios:
        mov eax, 36h
        mov ebx, stdin
        mov ecx, 5402h
        mov edx, termios
        int 80h
        ret

PrintNum:   
    push    lpBufOut
    push    esi 
    call    dwtoa

    mov     edi, lpBufOut
    call    GetStrlen
    inc     edx
    mov     ecx, lpBufOut
    mov     eax, sys_write
    mov     ebx, stdout
    int     80H     
    ret     

;~ #########################################  
GetStrlen:
    push    ebx
    xor     ecx, ecx
    not     ecx
    xor     eax, eax
    cld
    repne   scasb
    mov     byte [edi - 1], 10
    not     ecx
    pop     ebx
    lea     edx, [ecx - 1]
    ret

;~ #########################################      
dwtoa:
;~ number to convert = [ebp+8]
;~ pointer to buffer that receives number = [ebp+12]
    push    ebp
    mov     ebp, esp

    push    ebx
    push    esi
    push    edi

    mov     eax, [ebp + 8]
    mov     edi, [ebp + 12]

    test    eax, eax
    jnz     .sign

.zero:
    mov     word [edi], 30H
    jmp     .done

.sign:
    jns     .pos
    mov     byte [edi], "-"
    neg     eax
    add     edi, 1

.pos:
    mov     ecx, 3435973837
    mov     esi, edi

.doit:
    mov     ebx, eax
    mul     ecx
    shr     edx, 3
    mov     eax, edx
    lea     edx, [edx * 4 + edx]
    add     edx, edx
    sub     ebx, edx
    add     bl, "0"
    mov     [edi], bl
    add     edi, 1
    cmp     eax, 0
    jg      .doit

    mov     byte [edi], 0

.fixit:
    sub     edi, 1
    mov     al, [esi]
    mov     ah, [edi]
    mov     [edi], al
    mov     [esi], ah
    add     esi, 1
    cmp     esi, edi
    jl      .fixit

.done:    
    pop     edi
    pop     esi
    pop     ebx

    mov     esp, ebp
    pop     ebp
    ret     4 * 2

メイクファイル

APP = terminos
$(APP): $(APP).o
    ld -o $(APP) $(APP).o
$(APP).o: $(APP).asm
    nasm -f elf $(APP).asm
于 2013-03-01T00:18:23.307 に答える