News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Hello and Help Request @ Basics

Started by Brinuz, April 01, 2011, 05:19:23 PM

Previous topic - Next topic

dedndave

probably without knowing it, you have applied Horner's Rule (or what i like to call Ling Long Kai Fang)
some time ago, i wrote a set of functions that will convert integers of any practical size to decimal string
http://www.masm32.com/board/index.php?topic=12363.msg94779#msg94779
LLKF9_1 has three procs, one for signed, one for unsigned, and one that is mode selectable
it performs base conversion on up to 9 digits at a time, then converts them to ASCII, 4 digits at a time

Brinuz

@dedndave
Yea i didn't know it =o I will give a look at your code and see what I can learn from it ^^

@

Okay after learning a bit in this topic. I decided to create one "app" that will output every friday 13th from the year 1900 to the year 2000.

I know that the code isn't nearly to perfect. But that's why I'm posting it here. In search of Tips on what to improve and why. :p

.386
.model flat, stdcall
option casemap:none

include E:\masm32\include\windows.inc
include E:\masm32\include\kernel32.inc
include E:\masm32\include\masm32.inc
include E:\masm32\include\user32.inc

includelib E:\masm32\lib\user32.lib
includelib E:\masm32\lib\kernel32.lib
includelib E:\masm32\lib\masm32.lib

GetMonthMax PROTO month:DWORD,year:DWORD

.data
hStd dd ?
bytesOut dd ?
monthsTOne dd 1,3,5,7,8,10,12,0
monthsTZero dd 4,6,9,11,0
currentDay dd ?
currentMonth dd ?
currentYear dd ?
total dd 0
number dd ?

.code

;EAX will have the days of the given month on the given year.

GetMonthMax PROC month:DWORD,year:DWORD

    MOV EDX, month

                                ;Check if it is 31 days
    MOV EBX, offset monthsTOne
    TOne:
        CMP DWORD PTR [EBX], EDX
        JE endTOne
        ADD EBX, 4
        CMP DWORD PTR [EBX], 0
        JE continueTOne
        JMP TOne
    endTOne:
        MOV EAX, 31
        JMP endProc
    continueTOne:

    ; -------------------------------------------------------------------------

                                ;Check if it is 30 days
    MOV EBX, offset monthsTZero
    TZero:
        CMP DWORD PTR [EBX], EDX
        JE endTZero
        ADD EBX, 4
        CMP DWORD PTR [EBX], 0
        JE continueTZero
        JMP TZero
    endTZero:
        MOV EAX, 30
        JMP endProc
    continueTZero:

    ; -------------------------------------------------------------------------

                                ;Check if it is 28/29 days

    MOV EAX, year
    MOV ECX, 4
    DIV ECX

    CMP EDX, 0                  ;Check if Year % 4 Equals 0
    JNE endTFeb28

    MOV EAX, year
    MOV ECX, 100
    DIV ECX
   
    CMP EDX, 0                  ;Check if Year % 100 Equals 0
    JNE endTFeb
   
    MOV EAX, year
    MOV ECX, 400
    DIV ECX

    CMP EDX, 0                  ;Check if Year % 400 Equals 0
    JE endTFeb28
   
    endTFeb:
        MOV EAX, 29
        JMP endProc
   
    endTFeb28:
        MOV EAX, 28
   
    endProc:
    ret
   
GetMonthMax ENDP

START:

    MOV EDX, 5                  ;Starting day of 1900 year
    MOV ECX, 1900               ;Years - Starts at 1900, Ends at 2000
    yearsLoop:
        MOV EBX, 1              ;Months - Starts at 1, Ends at 12
        monthsLoop:
            infLoop:

                CMP EDX, 13
                JNE continueInfLoop
                push EAX                ;Uses EAX as a temporary store, saving the current value of it in the stack
                MOV EAX, total 
                INC EAX
                MOV total, EAX
                POP EAX                 ;Sets EAX value back from the stack

                continueInfLoop:
                ADD EDX, 7              ;Adds 7 days to the current day
                MOV currentDay, EDX     ;saves the current day
                MOV currentMonth, ECX   ;saves the current month
                MOV currentYear, EBX    ;saves the current year

                push ECX
                push EBX
                call GetMonthMax
                MOV ECX, currentMonth   ;Restore from the variable
                MOV EBX, currentYear    ;Restore from the variable

                MOV EDX, currentDay     ;Restore from the variable
                CMP EDX, EAX
                JL infLoop
                SUB EDX, EAX
            endInfLoop:

            INC EBX                     ;Next month
            CMP EBX, 13
            JNE monthsLoop
        endMonthsLoop:
       
        INC ECX                         ;Next year
        CMP ECX, 2001
        JNE yearsLoop
    endYearsLoop:

    ; -------------------------------------------------------------------------

    ;OUTPUT
    push -11
    call GetStdHandle
    MOV hStd, EAX

    MOV ECX, 10
    MOV EAX, total
    MOV EBX, 0

    ;Convert from Decimal to ASCII
    convertNum:
        MOV EDX, 0
        DIV ECX
        push EDX
        INC EBX
        CMP EAX, 0
        JNE convertNum
    convertEnd:

    ;Stack stores the number now in the correct order
    ;EBX will have the number lengh

    MOV ECX, EBX

    MOV EDX, offset number
    saveNumber:
        POP EAX                 ;recover one number from the stack to EAX and then save it
        ADD EAX, 48             ;To convert it into the correct ASCII code
        MOV BYTE PTR [EDX], AL  ;Save the number to the byte pointed by EDX
        INC EDX                 ;Next byte to save the next number
        DEC EBX                 ;Counter--
        CMP EBX, 0
        JNE saveNumber
    saveEnd:

    ;Write to Console
    push 0
    push offset bytesOut
    push ECX
    push offset number
    push hStd
    call WriteConsole

    ;Exit Process
    push 0
    call ExitProcess

END START


Mainly i want a tip on how to avoid the need to save every register on a variable before using them on the procedure.

                continueInfLoop:
                ADD EDX, 7              ;Adds 7 days to the current day
                MOV currentDay, EDX     ;saves the current day
                MOV currentMonth, ECX   ;saves the current month
                MOV currentYear, EBX    ;saves the current year

                push ECX
                push EBX
                call GetMonthMax
                MOV ECX, currentMonth   ;Restore from the variable
                MOV EBX, currentYear    ;Restore from the variable

                MOV EDX, currentDay     ;Restore from the variable
                CMP EDX, EAX
                JL infLoop
                SUB EDX, EAX
            endInfLoop:

dedndave

well - i dunno if my code is a good example   :P
whenever i post anything in here, they seem to tell me i am stupid

RuiLoureiro

Hi Brinuz,

replace this:
    MOV EAX, year

by this:
    xor edx, edx
    MOV EAX, year

because «div ECX» divide EDX:EAX by ECX and not only EAX by ECX !!! Ok ?

Brinuz

Quote from: dedndave on April 08, 2011, 11:40:03 AM
well - i dunno if my code is a good example   :P
whenever i post anything in here, they seem to tell me i am stupid

i'm pretty sure that for me it will be i guess? ;)

Quote from: RuiLoureiro on April 08, 2011, 11:41:45 AM
Hi Brinuz,

replace this:
    MOV EAX, year

by this:
    xor edx, edx
    MOV EAX, year

because «div ECX» divide EDX:EAX by ECX and not only EAX by ECX !!! Ok ?


I see, because of the 64 bits / 32 bits division. Thank you. Sure it is something i should do.

RuiLoureiro

«Mainly i want a tip on how to avoid the need to save every register on a
variable before using them on the procedure.»

Replace this:
                continueInfLoop:
                ADD EDX, 7              ;Adds 7 days to the current day
                MOV currentDay, EDX     ;saves the current day
                MOV currentMonth, ECX   ;saves the current month
                MOV currentYear, EBX    ;saves the current year

                push ECX
                push EBX
                call GetMonthMax
                MOV ECX, currentMonth   ;Restore from the variable
                MOV EBX, currentYear    ;Restore from the variable

                MOV EDX, currentDay     ;Restore from the variable
                CMP EDX, EAX
                JL infLoop
                SUB EDX, EAX
            endInfLoop:

By this:
                continueInfLoop:
                ADD EDX, 7              ;Adds 7 days to the current day
                ;MOV currentDay, EDX     ;saves the current day
                ;MOV currentMonth, ECX   ;saves the current month
                ;MOV currentYear, EBX    ;saves the current year
                push    edx
                push    ecx
                push    ebx
               
                push ECX
                push EBX
                call GetMonthMax
                ;MOV ECX, currentMonth   ;Restore from the variable
                ;MOV EBX, currentYear    ;Restore from the variable
                ;MOV EDX, currentDay     ;Restore from the variable
                pop     ebx
                pop     ecx
                pop     edx
               
                CMP EDX, EAX
                JL infLoop
                SUB EDX, EAX
            endInfLoop:


AND
replace this:
endTFeb:
        MOV EAX, 29
        JMP endProc

by this:
endTFeb:
        MOV EAX, 29
        ret

Brinuz

I was kinda afraid of doing that, because i could probably mess up with the call.

RuiLoureiro

OR
replace this:
GetMonthMax PROC month:DWORD,year:DWORD

by this
GetMonthMax PROC month:DWORD,year:DWORD
            push    edx
            push    ecx
            push    ebx

AND

replace this:

    endProc:
    ret   
GetMonthMax ENDP

by this:

    endProc:
    pop     ebx
    pop     ecx
    pop     edx
    ret   
GetMonthMax ENDP

Brinuz

Ok I understand the logic there. It could work I guess ;D

Thank you once again. Tips to improve are always welcome

RuiLoureiro

Quote from: Brinuz on April 08, 2011, 01:39:59 PM
Ok I understand the logic there. It could work I guess ;D

Thank you once again. Tips to improve are always welcome

Ok, using the last hint GetMonthMax doesnt destroy EDX, ECX and EBX
and we dont need to save on a variable

RuiLoureiro

Hi Brinuz,
             There is an error here:

.data
...
number dd ?         <<<---- here
----------------------------------

Replace this:

number dd ?

By this:

number db 20 dup (0)

Why ? number is a buffer for ascii digits