12

My information is coming from here. The assignment asks for a program that reads in no more than 20 characters, converts those characters to upper case, and then prints the input as capitals.

I have no idea how to access the input from int21/AH=0ah. I really can't ask a more precise question unless I understand what is linked above. Can someone explain? Also, I'm using TASM if that makes any difference. Also, I'm testing this on freedos.

UPDATE1:

Alright, thanks to your help, I believe I understand how the interrupt needs to be set up and behaves.

Setup: I have to designate a ds:dx where I want this buffer to exist

I have to set ds:dx to 20 (which sets the max number of characters the buffer can hold)

I have to set ds:dx+1 to 0 (which I think somehow set a min number of characters to read in)

Actually call int21/AH=0ah, which will go to ds:dx and interpret the preset bytes. It will halt the program while it waits for input

int21/AH=0ah will fill from ds:dx+2+n with my input (where n is the number of characters input including '\r')

My question is now, how do I do this. I've just looked through the x86 Assembly Language Reference again, but haven't been able to find anything helpful yet.

Code I've got so far

           assume          cs:code,ds:code
code       segment
start:

           mov  ax,code ;moves code segment into reg AX
           mov  ds,ax   ;makes ds point to code segment

           mov  ah,0ah
           int  21h
           mov  ax,1234h  ;breakpoint

           mov  ah,9
           mov  dx,offset message
           int  21h

endNow:
           ;;;;;;;;;;ends program;;;;;;;;;;
           mov  ah,0  ;terminate program
           int  21h   ;program ends

message    db   'Hello world!!!',13,10,'$'
code       ends
           end  start
wallyk
  • 56,922
  • 16
  • 83
  • 148

3 Answers3

10

That DOS function retrieves a buffer with user input. See this table. It seems that program is using that call to pause execution waiting for the user to resume the program.

Edit: I just reread the question. I thought you were only asking what the function call did in your given source. If you want to read input of no more than 20 characters, you first need memory to store it. Add something like this:

bufferSize  db 21  ; 20 char + RETURN
inputLength db 0   ; number of read characters
buffer      db 21 DUP(0) ; actual buffer

Then fill the buffer:

mov ax, cs
mov ds, ax ; ensure cs == ds
mov dx, offset bufferSize ; load our pointer to the beginning of the structure
mov ah, 0Ah ; GetLine function
int 21h

How to convert to uppercase is left to the reader.

Michael McGuire
  • 1,034
  • 9
  • 20
  • Then it behaves like int21/AH=1h which reads in a single character. I know that that interrupt puts the character into register AL. How would I figure out where the buffer of characters would be? –  Nov 03 '12 at 06:37
  • Also, I just realized. The offset table means that the actual character data begins at two bits or bytes (probably bytes) away from where the return data exists in memory. Thoughts? –  Nov 03 '12 at 06:39
  • Yes, the actual input starts at DS:DX + 2. However, this file ignores that input and only uses that function to pause execution. – Michael McGuire Nov 03 '12 at 07:10
  • 1
    Yes, my initial question was how the interrupt behaved because if I just asked how to implement it I would have no idea what you just posted meant. Thank you very much for the help. –  Nov 03 '12 at 07:45
  • shouldn't it be `mov dx, offset buffer` instead of `mov dx, offset bufferSize` ? and why does it display garbage value at first 2 bytes ? does that mean if i have to read 9 character ( including string terminator ) i would have of add 2 characters more ( first 2 garbage values ) 9 + 2 = 11 bytes ? – Ahtisham Nov 19 '17 at 08:27
  • @Ahtisham: No, the DOS call takes a pointer to the start of the struct, so it reads [dx+0] and [dx+2..n], and writes [dx+1]. Not [dx-2] and [dx-1] etc. which is what it would need if you passed a pointer to the start of the character-storage space. That would have been a valid design, but isn't what DOS chose. – Peter Cordes Nov 10 '22 at 18:57
3

That description says you put the address of a buffer in ds:dx before calling the interrupt. The interrupt will then fill that buffer with the characters it reads.

Before calling the interrupt, the first byte of the buffer is how many characters the buffer can hold, or 20 in your case. I do not understand the description of the second byte of the buffer (on input to the interrupt), so I would set it to zero. On return, that byte will tell you how many characters of input were read and placed into the buffer.

Nemo
  • 70,042
  • 10
  • 116
  • 153
  • So how I understand your explanation, the address where I can find the buffer is split across the registers ds and dx. –  Nov 03 '12 at 06:52
  • moot question, give me a minute to think about the above. –  Nov 03 '12 at 06:58
  • (fixing typo) Sort of. `ds` is the segment register; `dx` is the offset. And you do not "find" the buffer; you _provide_ the buffer by setting `ds` and `dx` to point to it before invoking the interrupt. (You also need to set the first two bytes of the buffer before invoking the interrupt. The buffer -- and its first two bytes -- are inputs to the interrupt.) – Nemo 11 mins ago – Nemo Nov 03 '12 at 07:07
  • The 2nd byte is output-only, not an input to the DOS call. Also no, as http://spike.scu.edu.au/~barry/interrupts.html#ah0a points out, on return the count is 1 less than the number of bytes written in the buffer, because the count doesn't include the final carriage-return. See also [How buffered input works](https://stackoverflow.com/q/47379024) for more details – Peter Cordes Nov 10 '22 at 18:55
0
.model small
.stack 100h
.data 
    N db ?
    msg db 10,13,09,"Enter number of arrays---->$"
.code   
.startup
    mov ax,@data
    mov ds,ax
    call read_N;read N from console




    mov ah,4ch
    int 21h  

Read_N  proc
    ;get number of arrays from user

    push ax
    push dx

 readAgain:   

    mov ax,03h ;Clear screen
    int 10h

    mov dx,offset msg
    mov ah,09h
    int 21h

    call ReadNumber

    ;Inuput number must be in 2<=N<=10 bounery  
    cmp al,2
    js readAgain ;input out of boundary read again
    cmp al,10
    jg readAgain 
    mov N,al
    pop dx
    pop ax
    ret
Read_N endp

ReadNumber proc
    ;read decimal number 0-99 using 
    ;character by character in askii and conver in to decimal   
    ;return result in al
    xor ax,ax
    xor bx,bx
    xor dx,dx

    mov ah,01h
    int 21h

    sub al,'0'  ;conver in to decimal
    mov bl,al  

    mov ah,01h
    int 21h 
    cmp al,0dh  ;Exit if enter pressed
    jnz cont  
    mov al,bl
    jmp exit
  cont:
    sub al,'0'  ;conver in to decimal
    mov dl,al  

    xor al,al
    xor bh,bh
    mov cx,bx
  addnum:    
    add al,10
 loop addnum  

    add al,dl
  exit:   
  ret
 ReadNumber endp  

end           
Bulwersator
  • 1,102
  • 2
  • 12
  • 30
free
  • 21
  • 1