News:

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

Array of strings, possible?

Started by Farbis, May 04, 2007, 03:52:41 PM

Previous topic - Next topic

Farbis

Hello! I've been reading all your topics for several months and so now i decide to join you.
Excuse me for my bad English but i'm French... I've bought the book of Kip Irvine to learn MASM6.15 (the only one i've found in France about MASM) and i have a "problem":
Is it possible to use an array of Strings (BYTE), i thought i could do it this way:

Monday EQU "Monday"
Tuesday EQU "Tuesday"
...
Sunday EQU "Sunday"

.data
sysTime SYSTEMTIME <>
DaysoftheWeek BYTE Monday,Tuesday,...,Sunday

I'm trying this because i use GetLocaltime function:

invoke GetLocalTime,ADDR sysTime
movzx eax,sysTime.wDayOfWeek
Depending on value of eax(5 for example) if want to display the day of the week (Friday) and i don't want to use many tests like
IF eax == 1
ELSEIF eax ==2
ELSEIF eax == 3,...
So i would like to acces to the element of the array and display it on the screen, but i can't find the right way
Can anyone help me please ? Sorry if it was so long.

MichaelW

One method would be to create a string table, padding each string with nulls to a uniform length:

DaysoftheWeek\
        db "Sunday",   0,0,0,0,0,0,0,0,0,0
        db "Monday",   0,0,0,0,0,0,0,0,0,0
        db "Tuesday",  0,0,0,0,0,0,0,0,0
        db "Wednesday",0,0,0,0,0,0,0
        db "Thursday", 0,0,0,0,0,0,0,0
        db "Friday",   0,0,0,0,0,0,0,0,0,0
        db "Saturday", 0,0,0,0,0,0,0,0

I used a 16-byte length so the offset address of the proper string can be simply calculated as the wDayOfWeek value shifted left by 4, added to the offset address of the table.

MSDN: SYSTEMTIME


eschew obfuscation

dsouza123

MichaelW

Well done, well thought out it requires no tests, very elegant solution.

DSouza123

Farbis

OK I'm gonna try this
I'd never had thought about this solution
Thank you for helping me
Au Revoir

Ratch

Farbis,

     Here is an example that uses an array of of 5 elements consisting of an integer index, two string addresses, and two string lengths.  The program was translated into MASM from a C program example found in Programming Windows, 5th Edition by Charles Petzold.  I included the C source and executable for comparison.  As you will see, it is done with MACROs.  Look at the .lst file and see how the array is generated.  Notice also that the strings are of variable length with no padding to make them a constant length.  Ask if you have any questions.  Ratch

[attachment deleted by admin]

lingo

Quote"Well done, well thought out it requires no tests, very elegant solution."

I disagree because it is not professional to add so much bytes for nothing..
If he used them for speed access it is OK(Ex: MMX), but here is for nothing...
What if we decide to add more strings for days of week in 20 different languages?
So, we use just a table (TablDays) with offsets of the strings:   :lol

;DaysoftheWeek\
enSun db "Sunday", 0
enMon db "Monday", 0
enTue db "Tuesday", 0
enWed db "Wednesday",0
enThu db "Thursday", 0
enFri db "Friday", 0
enSat db "Saturday", 0
frDim db "Dimanche", 0
frLun db "Lundi", 0
frMar db "Mardi", 0
frMer db "Mercredi", 0
frJeu db "Jeudi", 0
frVen db "Vendredi", 0
frSam db "Samedi", 0

TablDays dd  offset enSun   
dd offset enMon
dd offset enTue   
dd offset enWed
dd offset enThu   
dd offset en Fri   
dd offset enSat   
dd offset frDim
dd offset frLun
dd offset frMar
dd offset frMer
dd offset frJeu
dd offset frVen
dd offset frSam   

Usage:
mov ecx, [TablDays+eax*4]

Regards,
Lingo

skywalker

Is this similar to what you are doing ?


dw offset su, offset mo, offset tu, offset we, offset th, offset fr, offset sa
su db 'Sunday $'                                                                                                                                               
mo db 'Monday $'
tu db 'Tuesday $'
we db 'Wednesday $'
th db 'Thursday $'
fr db 'Friday $'                                                                           
sa db 'Saturday $'

BEGIN:
       mov     ax, cs
       mov     ds, ax
       mov     ah,2ah        ; date, month in dh, day in dl,
       int     21h           ; year in cx
       movzx   bx,al
       add     bx,bx
       mov     dx,cs:[days+bx] ; print day of the week

hutch--

Here is another approach, its not as simple as Michael's but it should be low enough overhead for the true fanatic.  :P


; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

comment * -----------------------------------------------------
                        Build this  template with
                       "CONSOLE ASSEMBLE AND LINK"
        ----------------------------------------------------- *


    day_by_num PROTO :DWORD


    .code

start:
   
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

    call main
    inkey
    exit

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

main proc

    invoke day_by_num,3

    ret

main endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

day_by_num proc num:DWORD

  ; ---------------------------------------------------------
  ; select day by number. Range is 1 to 7, Sunday to Saturday.
  ; ---------------------------------------------------------
    .data
      lblarr dd lbl0,lbl1,lbl2,lbl3,lbl4,lbl5,lbl6,lbl7,lbl8
    .code

    mov eax, num

    cmp eax, 7      ; handle overrun.
    ja lbl8

    jmp [lblarr+eax*4]

  lbl0:
    print "How do you get a zero length week ?",13,10
    ret
  lbl1:
    print "Today's Sunday",13,10
    ret
  lbl2:
    print "Mon day Itus",13,10
    ret
  lbl3:
    print "Today's Tuesday",13,10
    ret
  lbl4:
    print "Middle of the week Wednesday",13,10
    ret
  lbl5:
    print "Today's Thursday",13,10
    ret
  lbl6:
    print "Friday, weekend tomorrow",13,10
    ret
  lbl7:
    print "Today's Saturday",13,10
    ret
  lbl8:
    print "Your week is greater than 7 days ?",13,10
    ret

day_by_num endp

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««

end start
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

lingo

It is the normal usage: just a table (lblarr) with offsets of the strings  :lol

korte

DaysoftheWeek\
        db "Sunday",   0,0,0,0,0,0,0,0,0,0
        db "Monday",   0,0,0,0,0,0,0,0,0,0
        db "Tuesday",  0,0,0,0,0,0,0,0,0
        db "Wednesday",0,0,0,0,0,0,0
        db "Thursday", 0,0,0,0,0,0,0,0
        db "Friday",   0,0,0,0,0,0,0,0,0,0
        db "Saturday", 0,0,0,0,0,0,0,0



UGLY!




fixstring macro paramlist:VARARG
   for var,<paramlist>
      db var,16-@SizeStr(var)+2 dup(0)
   ENDM
ENDM

fixstring "Sunday","Monday","Tuesday".......


donkey

My post kinda got orphaned in the process of splitting off a running argument so I thought I would re-post it here, well at least the part about an alternate solution to long lists of month and day names. Windows already has an API dedicated to the task of converting SYSTEMTIME structures to date strings, the advantage is that it is locale specific and will output in whatever language the system is defaulted to. The GetDateFormat API  is by far the preferred method of date conversion

invoke GetLocalTime,OFFSET stLocal
invoke GetDateFormat,LOCALE_SYSTEM_DEFAULT,NULL,\
OFFSET stLocal,"dddd MMMM d yyyy",OFFSET szDateText,64


Will yeild:

Monday June 1 2007

Or if the user happens to run the program in France...

Lundi Juin 1 2007

To save an API call there is no need to get the local time unless it is required elsewhere, just set the SYSTEMTIME pointer (lpDate) to NULL

invoke GetDateFormat,LOCALE_SYSTEM_DEFAULT,NULL,\
NULL,"dddd MMMM d yyyy",OFFSET szDateText,64


Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

dsouza123

Interesting, four different methods for translating the day of the week
stored as a word value in the range 0 to 6 into an appropriate string.

Using .if .elseif etc requiring multiple compares and other overhead

Using fixed size storage for each day of the week string
no compares instead using shifted lookup taking advantage of uniform string size

Using variable sized string storage along with a uniform sized (dword) pointer table
no compares using an offset into the pointer table to get the address of the string

Using no in program storage and no compares
instead using the built in localization information in Windows by calling an API function

All have tradeoffs in space, time, and flexibility.


And I'll throw in a tweaked abbreviated english language version for good measure.


.data
DayOfWeek db "Sun",0,"Mon",0,"Tue",0,"Wed",0,"Thu",0,"Fri",0,"Sat",0,"   ",0

.code
movzx eax, sysTime.wDayOfWeek
mov   eax, dword ptr [DayOfWeek + eax*4]    ; eax ends up with a zero terminated string


It includes a final "   ",0 to maintain 16 byte alignment - or does it.  :wink

skywalker

How would I get this to print?

Thanks.

Would the print macro(console) work in this in order to keep the size down ?


invoke GetLocalTime,ADDR sysTime
movzx eax, sysTime.wDayOfWeek
mov   eax, dword ptr [DayOfWeek + eax*4]; eax ends up with a zero terminated string

MichaelW

The print macro expects a pointer. I'm not sure what the best method might be, but this should work OK:

; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    include \masm32\include\masm32rt.inc
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    .data
      sysTime SYSTEMTIME <>
      DayOfWeek db "Sun",0,"Mon",0,"Tue",0,"Wed",0
                db "Thu",0,"Fri",0,"Sat",0,"   ",0
    .code
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
start:
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
    invoke GetLocalTime,ADDR sysTime
    movzx eax, sysTime.wDayOfWeek
    mov eax, dword ptr [DayOfWeek + eax*4]

    push eax
    print esp,13,10
    pop eax

    inkey "Press any key to exit..."
    exit
; «««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««««
end start
eschew obfuscation

skywalker