Please help... newbie problems loading struct array with mixed data types

Started by iaNac, October 04, 2006, 02:21:27 AM

Previous topic - Next topic

iaNac

I'm transitioning from vb (recently) and pascal (decades ago) with very little asm background (tasm on a TRS80) and I'm hung up on some rookie stuff.  I've defined a structure as follows:

CRI struct
    DrugForm BYTE 32 dup (" ") ; example: "Metoclopramide 5.0 mg/ml"
    DrugDose REAL4 ? ; example: 1.25
    DrugUnits BYTE 12 dup (" ") ; example: "mg/kg/day"
    FluidRate REAL4 ? ; example (ml/hr): 8.3
    FluidVol DWORD ? ; example (ml): 1000
CRI ends

and an array in WinMain as follows:

WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
:
LOCAL cri[11]:CRI ; create array to hold 12 drugs
:

What I'd like to do now is load the array with data (12 drugs x 5 fields) at runtime before the window opens.  The initial goal being to load a combo box with cri
  • .DrugForm. But, from within a procedure, I'm having problems 1) assigning string values to DrugForm and DrugUnits and 2) assigning real numbers to DrugDose and FluidRate.  I thought about doing this in .data but I don't know how to work an array in that section.  Reals have me spooked since I don't even have strings figured out so 3) Is there a way to handle data like 1.25 without using Real4? I will later need these numbers for calculations that require 10ths or 100ths accuracy.  4) Curiosity: How are real numbers stored in memory, other than being pushed on the stack?  My ultimate goal is to allow users to expand the array with new drugs/doses and save these in a file.  If the file exists, load the array, otherwise use the inherent data (that I can't figure out how to provide!).  I've searched Iczelion's tutorials and AoA for examples but can't find one that fits my dilemma.  Any advice (or references) would be greatly appreciated.  I'll punt the struct array if there's a better way.

iaNac

uh, how'd that happen?  Sorry

PBrennick

iaNac,
You need to post the code.  Are we supposed to guess what mistakes you have made.  I could have fun with that!  Seriously, help us help you.

Are you familiar with FPU coding?  You will need to be.  There is a nice FPU library in masm32.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

Ratch

iaNac,

     Here is something to get you started.  The REAL4 word is 4 bytes long, just like the DWORD is.  It is interpreted in a particular way.  Read up on the FPU to get the format and operational details.  The code shows one way you can reference the 10 element of the array.  Ratch

[attachment deleted by admin]

sinsi

Are you going to do calculations with those REAL4s? If not, just store them as strings too.
Light travels faster than sound, that's why some people seem bright until you hear them.

iaNac

sinsi - yes, I'll need to do calculations.
Ratch - thanks for the zip (I'll look at it later - gotta get a root canal now)
PBrennick - sorry, I was trying to be conservative in my use of forum space.  How's everybody
get code to show in a grey box?

Here's more code as requested (WinMain).  I have made a few changes with no real progress.
Excuse all the comments, I'm still learning many basics.  I trimmed stuff out leaving this:

.486
.model flat,stdcall
option casemap:none

include iaNac32.inc ; windows,macros,masm32,gdi,user32,kernel32,Comctl

; PROTO section
    RegWinClass     PROTO :DWORD,:DWORD,:DWORD
    WinMain         PROTO :DWORD,:DWORD,:DWORD,:DWORD
    CreateComboBox  PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
    cbMsgInterp     PROTO :DWORD,:DWORD,:DWORD,:DWORD
    LoadCombo1      PROTO
    LoadCombo2      PROTO
    LoadCombo3      PROTO

; Structures
    CRI struct
        ; DrugForm  BYTE 32 dup (" ")
        DrugForm  DWORD   ?     ; (sas) ex. "Propofol 10.0 mg/ml"
        DrugDose  REAL4   ?     ; ex. 0.05
        ; DrugUnits BYTE 12 dup (" ")
        DrugUnits DWORD   ?     ; (sas) ex. "mg/kg/min"
        FluidRate REAL4   ?                     ; ex. 15.4         (ml/hr)
        FluidVol  DWORD   ?                     ; (sas) ex. 1000   (ml)
    CRI ends

; OMITTED: .DATA  .DATA?  .CONST and MACROS

.CODE   ; code section
start:

; get handles...
mov hInstance,FUNC(GetModuleHandle, NULL)       ; get handle to this program
mov CommandLine,FUNC(GetCommandLine)           ; get handle to CommandLine
mov hIcon, FUNC(LoadIcon,hInstance,MyIcon)       ; if MyIcon resource exists
mov hCursor,FUNC(LoadCursor,NULL,IDC_ARROW)  ; get handle to hCursor

; set variables...
mov bkgColor, COLOR_BTNFACE+1                ; set background color

; direct program flow to WinMain Loop...
invoke InitCommonControls
invoke WinMain,hInstance,NULL,CommandLine,WS_OVERLAPPEDWINDOW
; WinMain Loop is complete...
invoke ExitProcess, eax                      ; TERMINATE PROGRAM

; ««««««««««««««««««««««««««« WinMain Code Loop ««««««««««««««««««««««««««««

WinMain proc hInst:DWORD,hPrevInst:DWORD,CmdLine:DWORD,CmdShow:DWORD
LOCAL     msg:MSG
LOCAL      wc:WNDCLASSEX                     ; setup wc.WNDCLASSEX array
LOCAL   cri[11]:CRI

; ************************
; ** Problem area below **
; ************************

    ; >>>>> Store Drug Formulations...
    sas cri[0].DrugForm, "Lidocaine 2%"

    ; I think .DrugForm is still empty so sas probably wasn't right

    sas cri[1].DrugForm, "Metoclopramide 5.0 mg/ml"
    sas cri[2].DrugForm, "Procainamide 500.0 mg/ml"
    sas cri[3].DrugForm, "Propofol 10.0 mg/ml"
    ;fn MessageBox,hWnd,cri[0].DrugForm,"DrugForm",MB_OK ; CRASHES
    ;PrintStringByAddr cri[1].DrugForm       ; VKDebug returns no value
    ;PrintString cri[1].DrugForm                 ; VKDebug returns trash
    ;mov eax, cri[0].DrugForm                   ; mov pointer into eax?
    ;PrintDec eax                                     ; VKDebug returns 284481737
    ;PrintStringByAddr eax                        ; VKDebug returns no value
    ;mov eax, [cri[0].DrugForm]                ; mov pointer into eax?
    ;PrintDec eax                                    ; VKDebug returns 284481737

    ; >>>>> Store Drug Doses... (real4) also see code at Store Fluid Rates
    ; Data examples... Lido = 60.0, meto 1.0, procain 20.0, propofol 0.05
    mov eax, 60
    mov cri[0].DrugDose, eax ; would work if .DrugDose was DWORD
    ;fn MessageBox,hWnd,cri[0].DrugDose,"DrugDose",MB_OK ; CRASHES
    ;attempting real number...
    ;mov eax, 0.05 ; =====> error A2050: real or BCD number not allowed
    ;mov cri[0].DrugDose, 0.05 ; =====> error A2050

    ; >>>>> Store Drug Units...
    sas cri[0].DrugUnits, "mcg/kg/min"
    sas cri[1].DrugUnits, "mg/kg/day"
    sas cri[2].DrugUnits, "mcg/kg/min"
    sas cri[3].DrugUnits, "mg/kg/min"
    ;fn MessageBox,hWnd,cri[0].DrugUnits,"DrugUnit",MB_OK ; CRASHES

    ; >>>>> Store Fluid Rates... (real4)
    ; (bwKG default = 10 KG so (30xKG)+70=370ml / 24hr = 15.4 ml/hr)
    mov NumOfDrugs, 4                ; expand to 12 drugs later
    mov ecx, NumOfDrugs             ; also used in Store Fluid Volumes
    ;mov eax, 15.4 ; =====> error A2050
    mov esi, 0
    @@:
        mov cri[esi].FluidRate, eax
        ; PrintDec esi, "Fluid Rate Loop"
        inc esi
        cmp esi, ecx
        jne @B
    ;fn MessageBox,hWnd,cri[0].FluidRate,"FluidRate",MB_OK ; untested
    ;fn MessageBox,hWnd,cri[1].FluidRate,"FluidRate",MB_OK ; untested
    ;fn MessageBox,hWnd,cri[2].FluidRate,"FluidRate",MB_OK ; untested
    ;fn MessageBox,hWnd,cri[3].FluidRate,"FluidRate",MB_OK ; untested

    ; >>>>> Store Fluid Volumes...
    mov ecx, NumOfDrugs             ; still 4
    mov eax, 1000                       ; 1 liter default for all drugs
    mov esi, 0
    @@:
        mov cri[esi].FluidVol, eax
        ; PrintDec esi, "Fluid Vol Loop"
        inc esi
        cmp esi, ecx
        jne @B
    ;fn MessageBox,hWnd,cri[3].FluidVol,"FluidVol",MB_OK ; CRASHES

; ************************
; ** Problem area above **
; ************************

    ; register window's class...
    mov wc.cbSize,                 sizeof WNDCLASSEX
    mov wc.style,                   CS_HREDRAW or CS_VREDRAW or CS_BYTEALIGNWINDOW
    m2m wc.lpfnWndProc,       OFFSET WinProc   ; hWin uMsg handler
    mov wc.cbClsExtra,           NULL
    mov wc.cbWndExtra,        NULL
    m2m wc.hInstance,           hInstance
    m2m wc.hbrBackground,    bkgColor
    mov wc.lpszMenuName,     OFFSET MenuName
    m2m wc.lpszClassName,     OFFSET szClassName
    m2m wc.hIcon,                hIcon
    m2m wc.hIconSm,           hIcon
    m2m wc.hCursor,             hCursor
    invoke RegisterClassEx,     ADDR wc

    ; get window centering coordinates...
    CenterWindow 225, 175 ; returns ctr.overX, ctr.downY, ctr.wWid, ctr.wHgt

    ; create window to specs...
    invoke CreateWindowEx,WS_EX_OVERLAPPEDWINDOW,
        ADDR szClassName,
        ADDR szAppTitle,
        CmdShow,
        ctr.overX,ctr.downY,ctr.wWid,ctr.wHgt,
        NULL,NULL,
        hInst,NULL
        mov hWnd,eax                            ; get handle to main window

    ; display the window...
    invoke ShowWindow,hWnd,SW_SHOWNORMAL        ; display window on desktop
    invoke UpdateWindow,hWnd                                  ; repaint the client area

    ; Loop until PostQuitMessage is sent...
    .WHILE TRUE                                             ; Enter message loop
    invoke GetMessage, ADDR msg,NULL,0,0        ; wait for, then get uMsg
    .BREAK .IF (!eax)                                        ; break if PostQuitMessage
        invoke TranslateMessage, ADDR msg          ; send key ASCII to WM_CHAR
            ; perform key processing here
        invoke DispatchMessage, ADDR msg           ; send uMsg to WinProc
    .ENDW
    mov eax,msg.wParam           ; return exit code in eax (rarely useful?)
    ret
WinMain endp                         ; end WinMain code loop, ready to terminate

; ««««««««««««««««««««««««««««««« PROCEDURES «««««««««««««««««««««««««««««««

; OMITTED: WinProc, CreateComboBox, cbMsgInterp, LoadCombo1,
; LoadCombo2, LoadCombo3, rsrc.rc

end start   ; end of code section

Draakie

Hi iaNac,

I was very tempted to look at u're code / look again / and then run away as fast as possible. :lol

[ The Right Tools to start your'e discovery of Assembler Programming is required]


1.  Have a good look at the MASM32.lib - and it's companion help files
     the Zero Terminated String functions especially [EX:] szCatStr, szCopy
2. Get hold of the WIN32.hlp from the Forum-LINKS  - and all your'e API
    function calls are explained in detail [EX:] MessageBox
3. [PBrennick] was right - that FpuLib in MASM32 pack - is gonna help
    you LOTS - FPU programming is'nt something you just want to dive
    into.

Yes, the other Members in the Forum are probably going to help you with the
code you just posted. (Some are very brave souls indeed) . But if you are
going to learn this stuff - you've gotta walk the inch - we'll drag you the mile.

Draakie's Hubby
Does this code make me look bloated ? (wink)

iaNac

Draakie - Thanks.  I think I'm going about learning asm in an odd way.  I bought Irving's book which recommended TextPad as an editor so that's what I started with.  I have masm32 downloaded but I linked its help files to TextPad but overlooked masm32 Lib Help so I really appreciate your post.  I've already written this program in VB but it may not have been the best choice as a second asm program.   I'm obviously not ready for fpu stuff yet so this may be over my head but I'll keep pounding away.  Thanks again!

PBrennick

iaNac,
Here is an idea.  You said that you have already written this program in VB so why don't you compile it in debug mode so you can look at a meaningful dissassembly using OllyDbg.  Using this method, you can examine how VB dealt with some of the more difficult portions of your code.  Let us know if this is revealing.

To get your code into a gray box you click the code button which is one of the buttons above the smilies, the one with the # on it. It will put two tags into the post, just paste your code between the two tags.  You can click the preview button to see how you are doing and it will show you what we will see and then the

Paul
The GeneSys Project is available from:
The Repository or My crappy website

iaNac

Ratch - I took a look at your zip file and I really appreciate your time.  It will help me a lot!

PBrennick - I like that idea, unfortunately the CRI routine was a small component of a much larger program.  I might have trouble picking out the CRI from the rest.  I've played with OllyDbg only a little.  Does "compile it in debug mode" mean the same thing as dissassembling the .exe?  (It doesn't sound like it.)

iaNac

Draakie

Quote from: iaNac on October 05, 2006, 04:21:45 PM
Draakie - Thanks.  I think I'm going about learning asm in an odd way.  I bought Irving's book which recommended TextPad as an editor so that's what I started with. 

Ouch ! - Please have a look at RADASM by KetilO
(A very nice IDE - mnemonic, API etc. highlighting and loads, loads, loads more.)

A good IDE will make life simpler and would probably make you feel more comfortable
coming from a VB back-ground.

Draakie
Does this code make me look bloated ? (wink)

drizz

i can see some errors right away

>> LOCAL   cri[11]:CRI

when accessing such variables you must manually calculate offset,
masm doesnt auto calc it for you as HLLs do, it treats it as byte.

that is, instead of writing:

mov eax,cri[0].INeedDrugs
mov eax,cri[1].INeedDrugs

you must use:

mov eax,cri[0*(SIZEOF CRI)].INeedDrugs
mov eax,cri[1*(SIZEOF CRI)].INeedDrugs



assigning  a string:
.data
szDrug db "Andol",0
.code
invoke lstrcpy,addr cri[0*(SIZEOF CRI)].DrugForm,addr szDrug

The truth cannot be learned ... it can only be recognized.

PBrennick

drizz,
I fail to see how that could be right.  He is creating an array of 11 pointers.  Your method would result in all calculations except 0 being outside the array.  Please explain.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

sinsi

I think that if you use locals in your WinMain, nothing can see it -
LOCAL cri[11]:CRI

A couple of ideas:
- declare them in the .const section
- load them from a file into an allocated block
    - this will give you the option of a "user-modifiable" file maybe...
Light travels faster than sound, that's why some people seem bright until you hear them.

Ratch

iaNac,

     I should be whipped with a wet noodle for writing such bad code.  The following

MOV ESI,CRI                       ;ESI=size of CRI structure
SHL ESI,3                         ;ESI=8 times CRI structure
ADD ESI,CRI+@ Prescription        ;ESI=address of 10th element of array


should be replaced by

MOV ESI,9*CRI+@ Prescription      ;ESI=address of 10th element of array

  My apologies.
Ratch