Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
369 views
in Technique[技术] by (71.8m points)

assembly - Would this code for the scanf(); function work? (NASM 16-BIT)

I have this code for ASM that is supposed to replicate the scanf(); function. But I have a feeling that there is something wrong with the code. Here is the code:

  _scanf:
  MOV DS, 0
  JMP .continue
  RET

.continue
  MOV AH, 00h
  INT 0x16
  CMP AH, 0Dh
  JE .backspace
  CMP AL, 0x0D
  JE .done
  CMP AL, 0x0A
  JE .done
  MOV CX, 1
  MOV BH, 0
  MOV AH, 09h
  INT 0x10
  MOV AH, 03h
  INT 0x10
  ADD DL, 1
  MOV AH, 02h
  INT 0x10
  MOV WORD [DX+DS], AL
  ADD DS, 1
  JMP .continue

.done:
  RET

.backspace:
  MOV WORD [DX+DS], 0x00
  MOV AH, 03h
  INT 0x10
  SUB DL, 1
  MOV AH, 02h
  INT 0x10
  MOV BH, 0
  MOV AL, 0x00
  MOV CX, 1
  MOV AH, 09h
  INT 0x10
  JMP .continue

Is this valid code? Or is the [DX+DS] opcode an invalid segment override?

Using compiler NASM with 16-bit code.

question from:https://stackoverflow.com/questions/65838565/would-this-code-for-the-scanf-function-work-nasm-16-bit

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In the category "wrong" you have:

  • MOV DS, 0 not allowed on segment registers.
  • MOV WORD [DX+DS], AL not a valid addressing mode and also a mismatch between the 'WORD' tag and the byte size of AL.
  • ADD DS, 1 not allowed on segment registers.
  • MOV WORD [DX+DS], 0x00 not a valid addressing mode.

In the category "eyebrow" you have:

  • JMP .continue followed by RET making this RET unreachable.
  • Outputting via BIOS.WriteCharacterAndAttribute function 09h without specifying an actual attribute in the BL register. If you're unlucky you won't see anything appear on the screen.
  • Backspacing without checking if there's anything (left) to backspace over.

In the category "nit-picking" you have:

  • Comparing for backspace via the scancode in AH when it's shorter (and more usual) to do this via the ASCII code 8 stored in AL.
  • Writing a word-sized 0 in memory when you receive a backspace. A byte would be enough and nothing at all would be fine too.
  • Writing ASCII character 0 on the screen to remove a character. ASCII code 32 is the normal way to do this.

Below is a simplified version of your code. Make sure you have a buffer somewhere in your program. Use something like buffer times 80 db 0.
Since you don't seem to care about the color attribute, you can just as well use the Teletype function and not update the cursor yourself. Teletyping an ASCII code 8, moves the cursor to the left, but you have to write the space character yourself.

_scanf:
  mov  bx, 0007h    ; CONST DisplayPage and GraphicsColor
  mov  cx, 1        ; CONST ReplicationCount
  mov  di, buffer
.continue:
  mov  ah, 00h      ; BIOS.WaitKey
  int  16h          ; -> AX
  cmp  al, 8
  je   .backspace
  cmp  al, 13
  je   .done
  cmp  al, 10
  je   .done
  mov  [di], al     ; Write in buffer
  inc  di           ; Add to buffer
  mov  ah, 0Eh      ; BIOS.Teletype
  int  10h
  jmp  .continue
.backspace:
  cmp  di, buffer
  jna  .continue
  dec  di           ; Remove from buffer
  mov  ah, 0Eh      ; BIOS.Teletype (backspace)
  int  10h
  mov  ax, 0A20h    ; BIOS.WriteCharacter (space)
  int  10h
  jmp  .continue
.done:
  mov  byte [di], 0 ; Zero-terminate the string
  ret

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...