Вывод через wsprintf на assemblere

Дата публикации 14 сен 2022 | Редактировалось 30 авг 2025
Многие используют функцию wsprintf(), но не все знают, что в справке msdn есть 2 ошибки, которые могут в один прекрасный день убить ваш софт.
Код (ASM):
  1.  
  2. ; wsprintf( // Фоpматиpует и записывает в буфеp последовательность символов
  3. ;DWORD  lpOut, // Буфеp для пpиема отфоpматиpованных символов
  4. ;DWORD lpFmt, // Стpока упpавления фоpматом
  5. ; ... ); // Массив аpгументов для стpоки упpавления фоpматом
  6. ;==============================================================================
  7. ; В случае успешного завеpшения - число символов в lpOut,
  8. ; не считая 0 , в пpотивном случае - меньше, чем длина lpFmt.
  9. ;==============================================================================
  10. .386 ;
  11. .model flat,stdcall ;
  12. option casemap:none ;
  13. ;==============================================================================
  14. include c:\masm32\include\windows.inc
  15. include c:\masm32\include\kernel32.inc
  16. include c:\masm32\include\user32.inc
  17. includelib c:\masm32\lib\kernel32.lib
  18. includelib c:\masm32\lib\user32.lib
  19. ;==============================================================================
  20. .data ;
  21. ;==============================================================================
  22. lpOut db 255 dup(0) ;Здесь будет храниться результат (lpOut < 1024)!
  23. Message db "Result:",0 ;Заголовок MessageBox
  24. Unicode db 55h,0,6Eh,0,69h,0,63h,0,6Fh,0,64h,0,65h,0,0,0 ;строка в Unicode
  25. ;==============================================================================
  26. ; 1. Простейшие форматы lpFmt = %type
  27. ;==============================================================================
  28. lpFmtc db "%c",0 ;Single character
  29. lpFmtC db "%C",0 ;Single character
  30. lpFmtd db "%d",0 ;Signed decimal integer
  31. lpFmthc db "%hc",0 ;Single character
  32. lpFmthd db "%hd",0 ;Signed short integer
  33. lpFmths db "%hs",0 ;String
  34. lpFmthu db "%hu",0 ;Unsigned short integer
  35. lpFmti db "%i",0 ;Signed decimal integer
  36. lpFmtlc db "%lc",0 ;Single character
  37. lpFmtld db "%ld",0 ;Long signed integer
  38. lpFmtli db "%li",0 ;Long signed integer
  39. lpFmtls db "%ls",0 ;String
  40. lpFmtlu db "%lu",0 ;Long unsigned integer
  41. lpFmtlx db "%lx",0 ;Long unsigned hexadecimal integer
  42. lpFmtp db "%p",0 ;Win2000/XP hexadecimal pointer
  43. lpFmts db "%s",0 ;String
  44. lpFmtS db "%S",0 ;String
  45. lpFmtu db "%u",0 ;Unsigned integer
  46. lpFmtx db "%x",0 ;Unsigned hexadecimal integer
  47. ;==============================================================================
  48. ; 2. Сложные форматы lpFmt = %[-][#][0][width][.precision]type
  49. ;==============================================================================
  50. _lpFmtc db "char: %c",0
  51. _lpFmtC db "%C is char",0
  52. _lpFmtd db "4: %.4d",0
  53. _lpFmthc db "%hc : %04Xh",0
  54. _lpFmthd db "%hd is int.",0
  55. _lpFmths db "%-45hs%8d",0
  56. _lpFmthu db "-%.2hu",0
  57. _lpFmti db "(%i) = %i",0
  58. _lpFmtlc db "%lc*%lc",0
  59. _lpFmtld db "%ld kb/s",0
  60. _lpFmtli db "cool! , %li",0
  61. _lpFmtls db "len 4: %.4ls",0
  62. _lpFmtlu db "<%lu> MHz",0
  63. _lpFmtlx db "hex: %#08lx",0
  64. _lpFmtp db "pointer: %p",0
  65. _lpFmts db "string: %s ,len: %i",0
  66. _lpFmtS db "%S = %u bytes ...",0
  67. _lpFmtu db "int: %u.%u.%u.%u",0
  68. _lpFmtx1 db "hex: %04x-%04x-%04x-%04x",0
  69. _lpFmtx2 db "hex: #%.2lX%.2lX%.2lX",0
  70. _lpFmtx3 db "eax=%0.8X ebx=%0.8X ecx=%0.8X edx=%0.8X esi=%0.8X",13,10, \
  71.                 "edi=%0.8X ebp=%0.8X esp=%0.8X",0
  72. ;==============================================================================
  73. ; 3. Макрос
  74. ;==============================================================================
  75. lpFmt macro Text ;
  76.     local szText ;
  77. .data ;
  78. szText byte Text,0 ;
  79. .code ;
  80. exitm <offset szText>   ;
  81. endm ;
  82. ;==============================================================================
  83. .code
  84. start:
  85. ;==============================================================================
  86. ; 1. Примеры использования простейших форматов lpFmt
  87. ;==============================================================================
  88. invoke wsprintf,addr lpOut,addr lpFmtc ,65 ;
  89. call result ; "A"
  90. invoke wsprintf,addr lpOut,addr lpFmtC ,"a" ;
  91. call result ; "a"
  92. invoke wsprintf,addr lpOut,addr lpFmtd ,1 ;
  93. call result ; "1"
  94. invoke wsprintf,addr lpOut,addr lpFmthc,65 ;
  95. call result ; "A"
  96. invoke wsprintf,addr lpOut,addr lpFmthd,1 ;
  97. call result ; "1"
  98. invoke wsprintf,addr lpOut,addr lpFmths,addr Unicode ;
  99. call result ; "U"
  100. invoke wsprintf,addr lpOut,addr lpFmthu,1 ;
  101. call result ; "1"
  102. invoke wsprintf,addr lpOut,addr lpFmti ,1 ;
  103. call result ; "1"
  104. invoke wsprintf,addr lpOut,addr lpFmtlc,65 ;
  105. call result ; "A"
  106. invoke wsprintf,addr lpOut,addr lpFmtld,5872h ;
  107. call result ; "22642"
  108. invoke wsprintf,addr lpOut,addr lpFmtli,1 ;
  109. call result ; "1"
  110. invoke wsprintf,addr lpOut,addr lpFmtls,addr Unicode ;
  111. call result ; "Unicode"
  112. invoke wsprintf,addr lpOut,addr lpFmtlu,65 ;
  113. call result ; "65"
  114. invoke wsprintf,addr lpOut,addr lpFmtlx,01A2Bh ;
  115. call result ; "1a2b"
  116. invoke wsprintf,addr lpOut,addr lpFmtp ,65h ;
  117. call result ; "00000065"
  118. invoke wsprintf,addr lpOut,addr lpFmts ,addr Message ;
  119. call result ; "Result:"
  120. invoke wsprintf,addr lpOut,addr lpFmtS ,addr Unicode ;
  121. call result ; "Unicode"
  122. invoke wsprintf,addr lpOut,addr lpFmtu ,100 ;
  123. call result ; "100"
  124. invoke wsprintf,addr lpOut,addr lpFmtx ,01A2Bh ;
  125. call result ; "1a2b"
  126. ;==============================================================================
  127. ; 2. Примеры использования сложных форматов lpFmt
  128. ;==============================================================================
  129. invoke wsprintf,addr lpOut,addr _lpFmtc ,65
  130. call result
  131. invoke wsprintf,addr lpOut,addr _lpFmtC ,"a"
  132. call result
  133. invoke wsprintf,addr lpOut,addr _lpFmtd ,1
  134. call result
  135. invoke wsprintf,addr lpOut,addr _lpFmthc ,65,65
  136. call result
  137. invoke wsprintf,addr lpOut,addr _lpFmthd ,1
  138. call result
  139. invoke wsprintf,addr lpOut,addr _lpFmths ,addr Unicode,571
  140. call result
  141. invoke wsprintf,addr lpOut,addr _lpFmthu ,1
  142. call result
  143. invoke wsprintf,addr lpOut,addr _lpFmti ,1,1
  144. call result
  145. invoke wsprintf,addr lpOut,addr _lpFmtlc ,65,56
  146. call result
  147. invoke wsprintf,addr lpOut,addr _lpFmtld ,5872h
  148. call result
  149. invoke wsprintf,addr lpOut,addr _lpFmtli ,1
  150. call result
  151. invoke wsprintf,addr lpOut,addr _lpFmtls ,addr Unicode
  152. call result
  153. invoke wsprintf,addr lpOut,addr _lpFmtlu ,666
  154. call result
  155. invoke wsprintf,addr lpOut,addr _lpFmtlx ,01A2Bh
  156. call result
  157. invoke wsprintf,addr lpOut,addr _lpFmtp ,65h
  158. call result
  159. invoke wsprintf,addr lpOut,addr _lpFmts ,addr Message,sizeof Message-1
  160. call result
  161. invoke wsprintf,addr lpOut,addr _lpFmtS ,addr Unicode,sizeof Unicode
  162. call result
  163. invoke wsprintf,addr lpOut,addr _lpFmtu ,100
  164. call result
  165. invoke wsprintf,addr lpOut,addr _lpFmtx1 ,01A2Bh
  166. call result
  167. invoke wsprintf,addr lpOut,addr _lpFmtx2 ,01A2Bh
  168. call result
  169. invoke wsprintf,addr lpOut,addr _lpFmtx3 ,eax,ebx,ecx,edx,esi,edi,ebp,esp
  170. call result
  171. ;==============================================================================
  172. ; 3. Пример c использованием макроса
  173. ;==============================================================================
  174. invoke wsprintf,addr lpOut,lpFmt("%ld kb/s"),5872h
  175. call result
  176. invoke wsprintf,addr lpOut,lpFmt("Alert, sindrom vachtera detected, %li"),1
  177. call result
  178. ;==============================================================================
  179. invoke ExitProcess,0
  180. ;==============================================================================
  181. ; Вывод результата
  182. ;==============================================================================
  183. result proc
  184. invoke MessageBox,0,addr lpOut,addr Message,MB_OK
  185. ret
  186. result endp
  187. ;==============================================================================
  188. end start

5 7.212
who_know777

who_know777
Member

Регистрация:
29 мар 2021
Публикаций:
2

Комментарии


      1. alex_dz 19 сен 2022
        Спасибо, познавательная статья

        на самом деле проблема для ml64 представляет вот тот макрос, на него и ругаеться

        ;==============================================================================
        ; 3. Макрос
        ;==============================================================================
        lpFmt macro Text ;
        local szText ;
        .data ;
        szText byte Text,0 ;
        .code ;
        exitm <offset szText> ;
        endm ;


        конкретно при использовании макроса

        invoke wsprintf,addr lpOut,lpFmt("%ld kb/s"),5872h

        получаем

        Microsoft (R) Macro Assembler (x64) Version 14.00.24210.0
        Copyright (C) Microsoft Corporation. All rights reserved.
        Assembling: wsprn.asm
        ***************************
        ERROR Unknown argument type -> offset ??0199
        ***************************
        wsprn.asm(174) : error A2052:forced error
        REGISTER(22): Macro Called From
        procedure_call(11): Macro Called From
        invoke(1): Macro Called From
        wsprn.asm(174): Main Line Code
      2. who_know777 19 сен 2022
      3. alex_dz 19 сен 2022
        Спасибо за код,
        Пробую адаптировать на Masm64, получаю такие ошибки, просьба подсказать в чем дело
        ----------
        Microsoft (R) Macro Assembler (x64) Version 14.00.24210.0
        Copyright (C) Microsoft Corporation. All rights reserved.

        Assembling: wsprn.asm
        ***************************
        ERROR Unknown argument type -> offset ??0172
        ***************************
        ***************************
        ERROR Unknown argument type -> offset ??017B
        ***************************
        wsprn.asm(166) : error A2052:forced error
        REGISTER(22): Macro Called From
        procedure_call(11): Macro Called From
        invoke(1): Macro Called From
        wsprn.asm(166): Main Line Code
        wsprn.asm(168) : error A2052:forced error
        REGISTER(22): Macro Called From
        procedure_call(11): Macro Called From
        invoke(1): Macro Called From
        wsprn.asm(168): Main Line Code
      4. who_know777 16 сен 2022
        Мало букв?
      5. TermoSINteZ 16 сен 2022
        Вы серьезно думаете, что это статья?