-1

I have been comparing an fixed string and an input string. But its hard to figure what is the register of the input one, is it al, ah or whatever. I'm just a beginner and this is a painful language for a programmer lol jk. please help I really appreciate it thanks :)

mov dx, offset temp             ;string input
mov ah, 0ah
int 21h     

mov bl, "a"                     ;condition
cmp al, bl 
jne aw

mov dx, offset msgTrue          ;true
mov ah, 09
int 21h  

aw:                             ;false
mov dx, offset msgFalse
mov ah, 09
int 21h 


ret
    msg  db 10, 13, "           *         ************************************       *****$"
    msg1 db 10, 13, "          ***        *            Ticketing System      *        ***$"
    msg2 db 10, 13, "         *****       ************************************         *$" 
    msg3 db 10, 13, "                          ==========================$" 
    msg4 db 10, 13, "                          =  (a)Land               =$" 
    msg5 db 10, 13, "                          =  (b)Water              =$"
    msg6 db 10, 13, "                          =  (c)Air                =$" 
    msg7 db 10, 13, "                          ==========================$" 
    msg8 db 10, 13, "                           Choose Travel Type: $"
    temp db 2, 0, 3 dup("$") 

    msgTrue db 10, 13, "                           You selected Land$"
    msgFalse db 10, 13, "                           Invalid Input$" 
phuclv
  • 37,963
  • 15
  • 156
  • 475
Mang Tomas
  • 25
  • 1
  • 5

2 Answers2

2

You use syscall 0Ah (buffered input) http://spike.scu.edu.au/~barry/interrupts.html#ah0a so the data you read is in temp (the buffer)

0Ah reads n bytes from STDIN into a buffer

mov bx, OFFSET buffer pushes the address of buffer (here temp) in bx, this is needed for 0Ah

To fix the number of bytes read you can use e.g. mov byte [bx],15

see also this http://www.fysnet.net/kbbuffio.htm

mov bl, 'a'                     ;condition
cmp al, bl 
jne aw

compares two 8-bit values (char), see this http://x86.renejeschke.de/html/file_module_x86_id_35.html (AL,AH is 8 bit, AX is 16 bit and EAX is 32 bit (Extended AX))

See this https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture#General-purpose_registers_(16-bit_naming_conventions) for the 8-/16-/32-/64-bit naming conventions

This can be used to read the read input byte from the input buffer temp and compare it:

val DB 'a'
mov al, val                    ;condition
mov bx, OFFSET temp            ; address of temp in bx: bx is a pointer to first byte in temp now
;alternatively you can use  lea bx, [temp] 
add bx, 2                     ; structure of input buffer (here temp) http://spike.scu.edu.au/~barry/interrupts.html#dosbuf
mov dl, byte [bx]              ; writes the byte [bx] points to in dl - [bx] dereferences bx - the byte command treats bx as a char* - see https://www.cs.uaf.edu/2006/fall/cs301/lecture/10_02_pointer.html
cmp al, dl 
jne aw
ralf htp
  • 9,149
  • 4
  • 22
  • 34
  • why not point out that `cmp al, 'a'` would be simpler? No need to tie up bl when an immediate will work the same. There's even a special encoding for cmp-immediate-with-al, so it's only a 2 byte instruction even with the immediate. Also, what do you think is wrong with `mov bl, 'a'`? Most assemblers let you use character constants anywhere an integer constant can appear. Multi-char constants produce multi-byte integers. – Peter Cordes Mar 03 '16 at 09:53
  • Still really clunky compared to `cmp byte [temp], 'a'` / `jne`. Also note that 16bit effective addresses can't use dx as a base or index, only BX/BP + SI/DI. [16bit can't use a SIB byte, so they have to jam all the addressing modes into the mod/rm byte](http://stackoverflow.com/a/34058400/224132). This is just one of the many reasons 16bit code sucks and is a waste of time to learn. (Those restrictions don't exist in other modes). – Peter Cordes Mar 03 '16 at 10:00
  • I wasn't going to, but I can't leave inefficient code alone. >.< Thanks for sorting out the format of the input buffer. I'm not a DOS guy, and have no interest in learning DOS system calls, other than to try to help people on SO. Oh, BTW, `offset temp + '3'` is not the same as `offset temp + 3`. You're adding the ascii encoding >.<. And you should do it at assemble time, since it's an assemble-time constant, rather than doing it at runtime. And shouldn't it be `+2`? The first user-input character goes after the two count bytes, right? – Peter Cordes Mar 03 '16 at 10:24
  • You are right it is +2. When reading first it thought byte 02 in the buffer also has 'administrative function' (and then begin the user bytes...) – ralf htp Mar 03 '16 at 10:34
  • Other things still wrong with your code: `[dx]` is not a valid effective address. Your code won't assemble. Use `bx`, `bp`, `si`, or `di`. e.g. `mov si, offset temp + 2` / `cmp byte ptr [si], 'a'`. ([16bit does allow displacement-only effective addresses](http://www.ic.unicamp.br/~celio/mc404s2-03/addr_modes/intel_addr.html#HEADING2-26). 32bit effective addresses are the same, except without the limitations, and you can scale the index. (see the link in my earlier comment for a writeup I did on 32bit EAs)). You can waste instructions putting things in regs if you like, though :P – Peter Cordes Mar 03 '16 at 10:39
  • It would be `lea bx, [temp]`. LEA's source is always an effective address. At least your un-commented code should work now, even if it is even less efficient than the OPs. :P – Peter Cordes Mar 03 '16 at 13:07
1

The result is in memory, where you asked the system call to put it. See Ralf's answer.

Check the input like so:

    mov   dx, offset temp             ; input buffer
    mov   ah, 0ah                     ; buffered input syscall
    int   21h     

    ; select one of two messages to print
    mov   dx, offset msgTrue
    cmp   byte ptr [temp+2], 'a'      ; compare the first byte of user input
    je  .true
    mov   dx, offset msgFalse         ; conditionally skip this instruction
.true:

    mov ah, 09                        ; print string syscall
    int 21h

Notice how the mov ah / int 0x21 code only appears once, and the branch only skips over a single instruction. You could do it with cmov on a modern CPU, but cmov annoyingly doesn't have an immediate-source encoding.

See the comments on Ralf's answer for criticism of the bloated code that results from not just using immediate operands with cmp. You tie up a lot fewer registers this way, too, when using assemble-time constants.


Another option (instead of mov dx, offset msgFalse) would be add dx, offset msgFalse - msgTrue, which makes the immediate operand a small number (fitting within the -128 .. 127 range for using the imm8 encoding). It doesn't save any code bytes in 16bit code, though, because mov dx, imm16 is 3 bytes (dedicated opcode for every dest register), and add dx, imm8 is also three bytes (no dedicated opcode). This would save bytes in 32bit code, where addresses are 32bits.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847