Author Topic: Enter your age program  (Read 21703 times)

Offline sledge

  • Jr. Member
  • *
  • Posts: 19
Enter your age program
« on: August 23, 2011, 02:56:11 AM »
Code: [Select]
org 100h

mov ah, 9
mov dx, str1
int 21h

mov ah, 1
int 21h

mov ah, 9

cmp al, 37h

jz age_same
jg age_older
jl age_younger
jmp after

age_same:
mov dx, str2
int 21h
jmp after

age_older:
mov dx, str3
int 21h
jmp after

age_younger:
mov dx, str4
int 21h
jmp after

after:

mov ah, 4Ch
int 21h

str1 db 'ENTER YOUR AGE: $'
str2 db 0Ah, 'Wow. You and I are the same age.$'
str3 db 0Ah, 'You are older than me, pal. Cool!$'
str4 db 0Ah, 'I am older than you, haha!$s'

This wonderful program asks for your age, compare and then outputs a message based on how old you claimed to be.
Problem is I can't type more than one character... so in this program you cant be older than 9 years old.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Enter your age program
« Reply #1 on: August 23, 2011, 05:41:19 AM »
I see one serious error:

Code: [Select]
str4 db 0Ah, 'I am older than you, haha!$s'

Should be:

Code: [Select]
str4 db 0Ah, 'I am older than you, groan!$'

Seriously, is there a question in this? Do you want to be older than 9? (answer carefully - it doesn't stop at 9!) :)

If you want to be able to enter a multi-digit number, that can be arranged. You could either enter a string (int 21h/0Ah or int 21h/0C0Ah or maybe the "file read" interrupt on stdin...) and "convert" it to a number. Or, you could get input character-by-character as you're doing and "convert" to a number as you go along. I'd use a "no echo" input (int 21h/7 or int 21h/8 IIRC), and echo it only if it's a valid digit - maybe beep otherwise (char 07h). In either case:

; set a "result so far" to zero
; get a character (from keyboard or "string")
; if it's EOS, quit
; check that it's a valid decimal digit
; if not... display error? quit?
; multiply the "result so far" by ten
; convert the character to a number
; add it to "result so far"

Here's a "clever" (IMO) method which uses "lea" a couple times to multiply by ten, "convert" the character, and add it in. This is intended for 32-bit code, and expects the address of a string on the stack. It could probably be altered to work in 16-bit code, although you'd need to keep the 32-bit addressing modes... probably easier to just multiply by ten with "mul" in 16-bit code. It takes any non-digit as EOS, and doesn't check for overflow. It handles only unsigned (positive) numbers. You probably won't get any negative ages (although them pesky "users" will type in any darn thing - gotta watch 'em!). It illustrates the general idea...

Code: [Select]
atoi:
    mov edx, [esp + 4]  ; pointer to string
    xor eax, eax        ; clear "result"
.top:
    movzx ecx, byte [edx]
    inc edx
    cmp ecx, byte '0'
    jb .done
    cmp ecx, byte '9'
    ja .done
   
    ; we have a valid character - multiply
    ; result-so-far by 10, subtract '0'
    ; from the character to convert it to
    ; a number, and add it to result.
   
    lea eax, [eax + eax * 4]
    lea eax, [eax * 2 + ecx - 48]

    jmp short .top
.done
    ret

Your "jg" and "jl" are for signed numbers - "ja" and "jb" for unsigned. Unless someone claims to be very old, a signed number won't be interpreted as negative, so it shouldn't cause a problem...

Best,
Frank



Offline avcaballero

  • Full Member
  • **
  • Posts: 133
  • Country: es
    • Abre los Ojos al Ensamblador
Re: Enter your age program
« Reply #2 on: August 23, 2011, 10:23:44 AM »
Code: [Select]
; avch. You can input 2 characters, do not checking errors
MyAge   EQU  38
[org 100h]
[section .text]
  mov     dx, Text1
  mov     ah, 9
  int     21h
  mov     dx, Input
  mov     ah, 0Ah
  int     21h
  mov     si, Input+1
  xor     bh, bh
  cmp     byte [Input+1], 1
  mov     bl, byte [Input+2]
  jz      @next
    mov     bx, word [Input+2]
  @next:
  xor     ah, ah
  mov     al, bl
  and     al, 0Fh
  mov     cl, 10
  mul     cl
  mov     ah, bh
  and     ah, 0Fh
  add     al, ah
  cmp     al, MyAge
  mov     di, Text4 + 2     ; Let's suppose are equal
  ja      @Above
  jb      @Below
  jmp     @Next2
  @Above:
    mov     di, Text3 + 2
    jmp     @Next2
  @Below:
    mov     di, Text2 + 2
  @Next2:
  mov     ax, bx
  stosw
  sub     di, 4
  mov     dx, di
  mov     ah, 9
  int     21h
  ret

[section .data]
  Input      db 3, "    "
  Text1      db "How old are you?: $"
  Text2      db 13, 10, "   and you're not lying yet?$"
  Text3      db 13, 10, "  , take a soup and go to bed!$"
  Text4      db 13, 10, "  , What good vintage!$"
Greetings

Offline sledge

  • Jr. Member
  • *
  • Posts: 19
Re: Enter your age program
« Reply #3 on: August 25, 2011, 09:13:47 PM »
Didnt know there were more functions (in int 21h) that worked with user input, thought 1h was the only one, good to know, I'll try them out. I'm sorry if this is too obvious, but what do you mean by "I'd use a no echo input", I tried googling for echo but didnt find the meaning of this term when it comes to programming.

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Enter your age program
« Reply #4 on: August 25, 2011, 10:20:10 PM »
"Echo" just indicates whether the character is displayed on the screen or not.

http://www.ctyme.com/intr/int-21.htm

Compare ah=1 with ah=7 or 8. Check out ah=6 while you're there - kind of an "interesting" one. The bios int 16h can also be used.

If you're not familiar with "Ralf Brown's Interrupt List"...

http://www.cs.cmu.edu/~ralf/files.html

Ralf's your new best friend! Besides the actual "interrupt list", there's info on ports, memory, instructions... Almost "necessary" if you're going to mess with dos, and quite useful even if you're not!

The idea behind "no echo" input is to not even display the character if the user enters a "non-digit" - saves having to mess with "backspace". :)

By all means, try stuff out.  "Learning dos" is not that useful these days, but it's good experience writing asm, and it's "fun" (a matter of opinion, I suppose...)

Best,
Frank


Offline avcaballero

  • Full Member
  • **
  • Posts: 133
  • Country: es
    • Abre los Ojos al Ensamblador
Re: Enter your age program
« Reply #5 on: August 26, 2011, 11:06:33 AM »
Int 21h has many more than 1h function, for almost everything you need. Also, there is not only Int 21h interrupt. As Frank says, Ralf Brown's Interrupt List would be a good friend.

Regarding MS-DOS programming I think it is a clever task. I believe that, in the core, is not very different from Windows programming. One gives you interrupts to programming and other functions, but basically are the same. Moreover, if you learn DOS programming, I guess you can do it also in Windows without great difficulty. Besides, I think it is a pity losing decades of programming experience. That's at least my opinion.

Well, since we have the code above, I present the secret number guessing game. Indeed, this code fixes a small mistake in the previous one, of what no one seemed to have noticed.

Code: [Select]
; avch. Guess the secret number. Random routine need to be improved, but it should work
; hit CTRL+C at any time to exit
[org 100h]
[section .text]
  xor       ah, ah
  int       1ah 
  mov       word [RandSeed], dx
  @main:
    mov       cx, 30
    call      Random
    inc       dx
    mov       byte [Secret], dl
    xor       ah, ah
    mov       al, dl
    mov       cl, 10
    div       cl
    or        ax, 3030h
    mov       word [Text3+17], ax        ; The secret number in final text
    mov       cl, 5
    @Inner:
      mov       ch, cl
      or        ch, 30h
      mov       byte [Text1+27], ch      ; Attempts left in input text
      ; Input message
      mov       dx, Text1
      mov       ah, 9
      int       21h
      ; Get Response
      mov       dx, Input
      mov       ah, 0Ah
      int       21h
      call      GetResp
      call      Success
    jc        @Exit
    jnz       @Inner
    @Exit:
    ; ¿Exit?
    mov       dx, Text4
    mov       ah, 9
    int       21h
    xor       ah, ah
    int       16h
    or        al, 100000b
    cmp       al, 'y'
  jz        @main
  mov       dx, Text5
  mov       ah, 9
  int       21h
  ret
 
  Success:
    clc                                ; There are attempts, mark it
    cmp       al, byte [Secret]        ; Are we success?
    mov       dx, Text2                ; we suppose so
    jz        @SExit
      cmp       cl, 1
      ja        @Next1
        ; We have finished attempts
        mov       dx, Text3            ; We have finished, failed
        stc                            ; Mark it
        jmp       @SExit
      @Next1:
        ; We have not finished yet and we have not succeeded
        dec       cl                   ; One attempt less
        sub       al, byte [Secret]    ; Which is greather?
        mov       dx, Text6            ; Suppose lower
        js        @SExit0
          mov       dx, Text7          ; no, greather
    @SExit0:
      clc                              ; There are attempts, mark it
    @SExit:
    ; Print the message
    mov       ah, 9
    int       21h
  ret

  Random:
    ; Purpose : pseudo random number in [0, CL)
    ; In      : CX
    ; Out     : DL: número aleatorio
    ; Destoys : DX
    push      ax
    mov       ax, [RandSeed]
    mov       dx, 8405h
    mul       dx
    inc       ax
    mov       [RandSeed],ax
    xor       dx, dx
    div       cx
    pop       ax
  ret

  GetResp:
    ; Out     : al
    push    bx
    push    cx
    push    si
    mov     si, Input+1
    xor     bh, bh
    cmp     byte [Input+1], 1
    mov     bh, byte [Input+2]
    jz      @next
      mov     bx, word [Input+2]
    @next:
    xor     ah, ah
    mov     al, bl
    and     al, 0Fh
    mov     cl, 10
    mul     cl
    mov     ah, bh
    and     ah, 0Fh
    add     al, ah
    pop     si
    pop     cx
    pop     bx
  ret

[section .bss]
  RandSeed    resw  1
  Secret      resb  1

[section .data]
  Input       db    3, "    "
  Text1       db    13, 10, "Guess the number [1,30],   attempts: $"
  Text2       db    13, 10, "Right!", 13, 10, "$"
  Text3       db    13, 10, "Failed, it was   ", 13, 10, "$"
  Text4       db    13, 10, "Try again (Y/N)?$"
  Text5       db    13, 10, 13, 10, "Take a look at http://www.abreojosensamblador.net/", 13, 10, "bye!$"
  Text6       db    13, 10, "Too low", 13, 10, "$"
  Text7       db    13, 10, "Too high", 13, 10, "$"

Cheers!