home *** CD-ROM | disk | FTP | other *** search
/ CD Shareware Magazine 1997 January / CD_shareware_1-97.iso / DOS / PRG / STRUC.ZIP / STRUC.ASM < prev   
Encoding:
Assembly Source File  |  1996-02-17  |  7.8 KB  |  221 lines

  1. ; I'll be using the extended  registers,  so  ".386"  is required here. I'm
  2. ;  using  simplified  directives  here. However, there is no reason why   I 
  3. ;  can't declare my own segments. I  will  probably  give  a sample of that 
  4. ;  in a future upload or an appended version of this upload.
  5. .386
  6.  
  7. ;-----I'll be accessing extended memory  while  in  protected mode.  In that 
  8. ;      mode, memory is like one of  those  long "flat" highways  across  the 
  9. ;      western U.S. deserts. The 32RTM shares the  same  data  selector with 
  10. ;      SS, ES, and DS, so addressing variables  and other items that require
  11. ;      an offset are seamlessly  integrated  between  modules.  Using the "C" 
  12. ;      calling convention eliminates the  need for the preceding underscores.
  13. .model flat, c
  14.  
  15. ;-----The assembler structure which makes it easy to manipulate data between 
  16. ;      the C++ module and here
  17. mystruct struc
  18. ascii_char      db   0
  19. unsigned_char   db   0
  20. short           dw   0
  21. unsigned_short  dw   65535
  22. long            dd   0
  23. unsigned_long   dd   0
  24. string          db   13, 10, "This is the string from the .asm routine", 0
  25. mystruct ends
  26.  
  27. ;----- This will  be  the  data  segment. It  is of course not segmented the
  28. ;       same as in real mode, but is defined that way.
  29. .data
  30. str             db      10, 13, "This is the value passed by way of the .asm's private stack: $"
  31. str2            db      "This is the address of assembler stack: $"
  32.  
  33. ;----- Define some default variables for my structure
  34. struct_1 mystruct <>
  35.  
  36. ;----- Set up my  inner  stack.  I've  used  the current location counter to
  37. ;       obtain the address of the  end of  my  stack. 
  38.  
  39. public          end_stack
  40. inner_stack dd 200h dup (0)
  41. end_stack       = $ 
  42.  
  43. ;----- I'll save the values of  esp, and  ebp  upon program entry. I'll also
  44. ;       create space to hold the argument (pointer) passed by the C++ module.
  45. esp_save        dd  ?
  46. ebp_save        dd  ?
  47.  
  48. struct_ptr      dd  ?
  49.  
  50. ;----- Here  is  the  declaration  of the  section where the code will begin.
  51. ;       Variables  can  go  here  as  well.  Note,  that  even  though it is 
  52. ;       certainly  possible  to (by  using  an  alias  descriptor), it's not 
  53. ;       really normal, nor  keeping with tradition  to  write  to  the  code 
  54. ;       area (modify variables)  while operating in  protected mode. 
  55. .code
  56.  
  57. ;----- Since this routine will be "called" from the C++ module, it must of
  58. ;       course be made "public"
  59. public  fill_struct
  60.  
  61. ;----- all procedures  in  protected mode are of type "near". Something that
  62. ;       i've noticed when compiling using Power Pack is that "near" actually
  63. ;       has to  be  declared here. Whereas usually it will default to "near"
  64. ;       here  as  long  as  "near"  is declared at the end of the procedure.
  65. fill_struct proc  near 
  66.  
  67. ;----- This  is  the  argument  that  was passed to here from the C++ module
  68. ARG the_struct:dword
  69.  
  70. ;----- I have the most  success  saving  and  repositioning reference to the 
  71. ;       stack using this method. I often  prefer  to define a separate stack 
  72. ;       within  my assembler module. This  lays  the ground-work to do that.
  73. mov     ebp_save, ebp
  74. mov     esp_save, esp
  75.  
  76. ;----- Since I'm not addressing variables passed on the  C++  module's stack, 
  77. ;      this line isn't  "really"  necessary.  The  argument(s)  was  already 
  78. ;      addressed correctly by the "ARG" directive used above. I'll  do  this
  79. ;      here, just because it's a good habit
  80. mov     ebp, esp
  81.  
  82. ;----- Reset stack pointer to point at my stack. Then  check  the  integrity
  83. ;       of the new stack by filling and then dumping it.
  84. lea   edx, end_stack 
  85. mov   esp, edx
  86.  
  87. mov  cx, 01fch 
  88. loop_check:
  89. push eax
  90. dec  cx
  91. jnz  loop_check
  92.  
  93. mov  cx, 01fch 
  94. loop_check_2:
  95. pop  eax
  96. dec  cx
  97. jnz  loop_check_2
  98.  
  99.  
  100. ;----- This will  load  the  EBX register with the address of the  structure 
  101. ;       within the C++ module. This also makes it quite convenient to access 
  102. ;       character sequences of structured type. I'll also save this argument
  103. ;       just out of habit, so I  don't have to worry about finding it on the
  104. ;       stack if I need it later.
  105. mov  ebx, [the_struct]
  106. mov  [struct_ptr], ebx
  107.  
  108. ;----- The  following  code  will use  the  offset values from my  assembler
  109. ;       routine  to  load  values  into  the structure within the C++ module.
  110. ;       This is the  actual  loading  of the structure within the C++ module. 
  111. ;       I can also, first  fill  my   structure here, with the data I desire, 
  112. ;       and  then  send  a copy of that data to the C++ module. I'll do that 
  113. ;       with  the  variable  representing  an  unsigned character. I'll also 
  114. ;       use  two  of  the  default  defined  values  from my (only) "defined" 
  115. ;       structured  data  of  type  "mystruct".  The  two  members  that are 
  116. ;       pre-defined, as "unsigned_short" and "string".
  117.  
  118. mov  [ebx].ascii_char, -'~'
  119.  
  120. mov  [struct_1.unsigned_char], 255
  121. mov  cl, [struct_1.unsigned_char]
  122. mov  [ebx].unsigned_char, cl  
  123.  
  124. mov  [ebx].short, -32767
  125.  
  126. mov  cx, [struct_1.unsigned_short]
  127. mov  [ebx].unsigned_short, cx
  128. mov  [ebx].long, -2147483647
  129. mov  [ebx].unsigned_long, 4294967295
  130.       
  131. ;----- This  is  the  code  used to  copy  our  string over to the allocated
  132. ;       array  within  the  C++ module. Note  that I've terminated the array
  133. ;       with 0, since I believe that to be  what the C++ print function will 
  134. ;       look for as a  terminator.  Also note that although the value  in CX 
  135. ;       can exceed the actual length of  the  string  from  this  module, it 
  136. ;       -MUST NOT-  exceed the  size  of the allocated  array within the C++ 
  137. ;       module. Also  note  that  even  though  I'm  only moving a byte at a 
  138. ;       time here, there is  no reason,  one  cannot  move 32 bits at a time.
  139.  
  140. mov  edx, offset struct_1.string 
  141. mov  cx, 54
  142. cld
  143. repeat:
  144.  
  145. mov  al, [edx]            
  146. mov  [ebx].string, al     
  147. inc  edx
  148. inc  bx
  149. dec  cx
  150. cmp  cx, 0
  151. jne  repeat
  152.  
  153. ;----- Now we'll return the saved stack type registers.
  154. mov  esp, esp_save
  155.  
  156. mov  ebp, ebp_save
  157.  
  158. ret
  159. fill_struct endp
  160.  
  161.  
  162. ;----- I use  this  procedure to get and pass a pointer to my .asm module's
  163. ;       internal  stack  (the one I created above).  Now, all this internal
  164. ;       stack stuff is kind of silly, in the simple way that it's used here.
  165. ;       However, it can prove useful in expanded applications.
  166. public get_stack_pntr
  167.  
  168. get_stack_pntr proc near
  169.  
  170. lea eax, end_stack
  171.  
  172. ret
  173. get_stack_pntr endp
  174.  
  175.  
  176.  
  177. ;----- The  following  procedure  retrieves,  converts to ascii decimal, and
  178. ;       outputs  the  value  that  was place on this module's internal stack
  179. ;       by the C++ module.
  180. public print_stack_value
  181. print_stack_value proc near
  182.  
  183. push ebp
  184. mov  ebp, esp
  185. mov  [esp_save], esp
  186.  
  187. mov  edx, offset str
  188. mov  ah, 09h
  189. int  21h
  190.  
  191. mov  edx, offset end_stack - 4  ;backstep four, to point to end of my stack.
  192. mov  esp, edx  ;point SP to our stack
  193. pop  edx       ;pop from our stack
  194. add  dl, 30h
  195. mov  ah, 02h
  196. int  21h
  197. mov  dl, 10
  198. int  21h
  199. mov  dl, 13
  200. int  21h
  201.  
  202. mov esp, [esp_save]
  203. pop ebp
  204.  
  205. ret
  206. print_stack_value endp
  207.  
  208.  
  209.  
  210. ;----- That's all there is to it.  Pretty  easy don't  you think?  I haven't
  211. ;      been using the PowerPack's 32RTM all that long, so am not sure of all 
  212. ;      the things  it's  capable  of.  The "flat" memory  addressing and the
  213. ;      DOS string write herein  seemed  to  work  just  fine. I did a lot of  
  214. ;      shuffling of pointers, and everything  still came out pretty straight.
  215. ;      Keep in mind, that most of this  code  has  been  put together rather 
  216. ;      "loosely", as it's meant only  to  be used as a springboard for those
  217. ;      who might need a little  something to get the creative juices flowing.
  218. ;        Now.... let's give Borland a round of applause for their 
  219. ;        Power Pack product!
  220. end
  221.