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.
uh, how'd that happen? Sorry
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
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]
Are you going to do calculations with those REAL4s? If not, just store them as strings too.
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
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
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!
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
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
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
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
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
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...
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
Ratch,
That looks right to me, also. I think that was what drizz was trying to do.
Paul
Quote from: PBrennick on October 06, 2006, 12:08:15 PMI 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.
He is creating an array of 11 structures, not 11 structure pointers.
"LOCAL cri[11]:PTR CRI" would be 11 structure pointers.
When accessing elements of an array calculation for offset must be done
because square brackets in asm dont have the same meaning as square brackets in HLLs.
Step By Step Examples:byte arraylocal barray[100]:byte
mov al,barray[1*(sizeof byte)]
mov al,barray[2*(sizeof byte)]
optionally instead of "*sizeof byte" you can use "*TYPE barray"
word arraylocal warray[100]:word
mov ax,warray[1*(sizeof word)]
mov ax,warray[2*(sizeof word)]
optionally instead of "*sizeof word" you can use "*TYPE warray"
dword arraylocal dwarray[100]:dword
mov eax,dwarray[1*(sizeof dword)]
mov eax,dwarray[2*(sizeof dword)]
optionally instead of "*sizeof dword" you can use "*TYPE dwarray"
struct arraylocal structarray[100]:SOMESTRUCT
mov eax,structarray[1*(sizeof SOMESTRUCT)].element
mov eax,structarray[2*(sizeof SOMESTRUCT)].element
optionally instead of "*sizeof SOMESTRUCT" you can use "*TYPE structarray"
for accessing structure elements in a loop:
; >>>>> Store Fluid Volumes...
xor ecx,ecx
xor esi,esi
mov eax,1000 ; 1 liter default for all drugs
.while ecx<NumOfDrugs ; still 4
; PrintDec ecx, "Fluid Vol Loop"
mov cri[esi].FluidVol, eax
add esi,sizeof CRI
.endw
drizz,
You don't need to use 'sizeof' or 'type' all the time. If you want to code the size of a byte, you can code MOV AL,5*BYTE instead of MOV AL,5*(sizeof byte)] . Similiarly, 2*(size of SOMESTRUCT) can be coded as 2*SOMESTRUCT. Ratch
i somehow knew you would write that :), Yes i know (i just forgot to write the third option).
its my personal preference to use sizeof, as i use it in C,C++ too.
everyone his own :P
Ratch - I finally had time to study your example and found it extremely helpful. I got a lot out of it!
Thanks again - iaNac