文章目录

  • 查看 C++ ASM
    • 在线 C++ 反汇编
    • g++ -S
    • VS 调试时断点查看反汇编信息
    • VS 在项目属性的文件输出源码+汇编
      • Debug 下的:[ProjectName].asm
      • Release 下的:[ProjectName].asm
  • VS 调试数据
    • 模块
    • 进程
    • 内存
    • 寄存器
    • 在内存中的一些字符表信息
  • 编译出来的ASM文件通常包含的数据
    • 基本分段/分块
    • 反汇编实例
      • Debug下的反汇编
      • Release下的反汇编
    • 删除 JMC 汇编检测代码 - CheckForJustMyCode
  • 栈帧
    • 总结
      • 栈帧
        • EBP, ESP, EIP
        • 调用函数前
        • 调用函数内
        • 其他常用寄存器 EAX
        • call 指令
        • ret 指令
          • ret 后无数值
          • ret 后有数值的
        • 调用函数末端-返回-清理栈
          • _stdcall
          • _cdecl
  • References

学习目的:

  • 便于理解部分 shader 反汇编 后的代码查看
  • 便于处理部分业务逻辑层的算法、逻辑优化等
  • 如果未来有空,我会尝试自己写一个新的语言出来玩玩(但也就是提供具体的语法,逻辑运算,函数调用等功能的编译器 就够了,深入开发需要很巨量工作量。而且如果还加上预编译器链接器编译器的代码优化,那就麻烦了。因为一门语言要活跃起来需要软件生态支持,需要巨量的时间去实现各种现成库、调式工具等,来给使用者提高开发效率,否则没有意义,但如果是为了学习原理去重新一个简单的还是可以的。)

查看 C++ ASM

查看C++的ASM有好几种方式,不同的编译器,不同的版本,不同的ASM风格编译出来都不一样(汇编语法风格:有:Intel,AT&T的)

在线 C++ 反汇编

https://godbolt.org/
在这里插入图片描述

g++ -S

有这么一段C++程序:

int main()
{int a = 1;int b = -1;return a + b;
}

编译:g++ -S .\a.cpp,得到:a.s 文件:

	.file	"a.cpp".text.def	___main;	.scl	2;	.type	32;	.endef.globl	_main.def	_main;	.scl	2;	.type	32;	.endef
_main:
LFB0:.cfi_startprocpushl	%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl	%esp, %ebp.cfi_def_cfa_register 5andl	$-16, %espsubl	$16, %espcall	___mainmovl	$1, 12(%esp)movl	$2, 8(%esp)movl	12(%esp), %edxmovl	8(%esp), %eaxaddl	%edx, %eaxleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc
LFE0:.ident	"GCC: (MinGW.org GCC Build-20200227-1) 9.2.0"

VS 调试时断点查看反汇编信息

VS 下有好几种方法可以查看 MSVC 的编译器 CL.exe 编译出来的 C++ 汇编代码。

有这么一段C++程序:

int main()
{int a = 1;int b = -1;return a + b;
}

中断点后,在菜单栏选择:调试->窗口->反汇编(Ctrl+Alt+D)
在这里插入图片描述
反汇编结果

--- D:\jave\Work Files\CPP\dasm\DASM\DASM\DASM.cpp -----------------------------1: int main()2: {
00AC1700  push        ebp  
00AC1701  mov         ebp,esp  
00AC1703  sub         esp,0D8h  
00AC1709  push        ebx  
00AC170A  push        esi  
00AC170B  push        edi  
00AC170C  lea         edi,[ebp-0D8h]  
00AC1712  mov         ecx,36h  
00AC1717  mov         eax,0CCCCCCCCh  
00AC171C  rep stos    dword ptr es:[edi]  
00AC171E  mov         ecx,offset _3D4FA793_DASM@cpp (0ACC000h)  
00AC1723  call        @__CheckForDebuggerJustMyCode@4 (0AC1208h)  3:     int a = 1;
00AC1728  mov         dword ptr [a],1  4:     int b = -1;
00AC172F  mov         dword ptr [b],0FFFFFFFFh  5:     return a + b;
00AC1736  mov         eax,dword ptr [a]  
00AC1739  add         eax,dword ptr [b]  6: }
00AC173C  pop         edi  6: }
00AC173D  pop         esi  
00AC173E  pop         ebx  
00AC173F  add         esp,0D8h  
00AC1745  cmp         ebp,esp  
00AC1747  call        __RTC_CheckEsp (0AC1212h)  
00AC174C  mov         esp,ebp  
00AC174E  pop         ebp  
00AC174F  ret  

VS 在项目属性的文件输出源码+汇编

项目属性->配置属性->C/C+±>输出文件->汇编程序输出->带源代码的程序集(/FAs)

注意 Debug、Release 下的项目属性是分开调整的。
在这里插入图片描述
接下来直接编译编译生成项目,这里我是在Debug下测试的,所以在Debug目录下可以看到有Dasm.asm文件,如下:
在这里插入图片描述

CPP的源码还是和上面的一样,查看一样 DASM.asm的汇编源码是怎么样的:

Debug 下的:[ProjectName].asm

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.25.28610.4 TITLE	D:\jave\Work Files\CPP\dasm\DASM\DASM\DASM.cpp.686P.XMMinclude listing.inc.model	flatINCLUDELIB MSVCRTD
INCLUDELIB OLDNAMESmsvcjmc	SEGMENT
__3D4FA793_DASM@cpp DB 01H
msvcjmc	ENDS
PUBLIC	_main
PUBLIC	__JustMyCode_Default
EXTRN	@__CheckForDebuggerJustMyCode@4:PROC
EXTRN	__RTC_CheckEsp:PROC
EXTRN	__RTC_InitBase:PROC
EXTRN	__RTC_Shutdown:PROC
;	COMDAT rtc$TMZ
rtc$TMZ	SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ	ENDS
;	COMDAT rtc$IMZ
rtc$IMZ	SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
rtc$IMZ	ENDS
; Function compile flags: /Odt
;	COMDAT __JustMyCode_Default
_TEXT	SEGMENT
__JustMyCode_Default PROC				; COMDATpush	ebpmov	ebp, esppop	ebpret	0
__JustMyCode_Default ENDP
_TEXT	ENDS
; Function compile flags: /Odtp /RTCsu /ZI
; File D:\jave\Work Files\CPP\dasm\DASM\DASM\DASM.cpp
;	COMDAT _main
_TEXT	SEGMENT
_b$ = -20						; size = 4
_a$ = -8						; size = 4
_main	PROC						; COMDAT; 2    : {push	ebpmov	ebp, espsub	esp, 216				; 000000d8Hpush	ebxpush	esipush	edilea	edi, DWORD PTR [ebp-216]mov	ecx, 54					; 00000036Hmov	eax, -858993460				; ccccccccHrep stosdmov	ecx, OFFSET __3D4FA793_DASM@cppcall	@__CheckForDebuggerJustMyCode@4; 3    :     int a = 1;mov	DWORD PTR _a$[ebp], 1; 4    :     int b = -1;mov	DWORD PTR _b$[ebp], -1; 5    :     return a + b;mov	eax, DWORD PTR _a$[ebp]add	eax, DWORD PTR _b$[ebp]; 6    : }pop	edipop	esipop	ebxadd	esp, 216				; 000000d8Hcmp	ebp, espcall	__RTC_CheckEspmov	esp, ebppop	ebpret	0
_main	ENDP
_TEXT	ENDS
END

上面Debug下的调试信息太多了,再调整到Release,生成看看:

Release 下的:[ProjectName].asm

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.25.28610.4 TITLE	d:\jave\work files\cpp\dasm\dasm\dasm\dasm.cpp.686P.XMMinclude listing.inc.model	flatINCLUDELIB OLDNAMESEXTRN	@__security_check_cookie@4:PROC
PUBLIC	_main
; Function compile flags: /Ogtp
; File D:\jave\Work Files\CPP\dasm\DASM\DASM\DASM.cpp
;	COMDAT _main
_TEXT	SEGMENT
_main	PROC						; COMDAT; 3    :     int a = 1;
; 4    :     int b = -1;
; 5    :     return a + b;xor	eax, eax; 6    : }ret	0
_main	ENDP
_TEXT	ENDS
END

可以看到,Release 下,因:代码优化 后,return 之前的一些代码,压根没生成对应的汇编处理,因为MSVC cl.exe 下编译的Main函数是否返回值,都无关紧要的。

当然,如果你仍然想在Release “比较干净”的代码上查看asm,可以打开项目配置:C/C++->优化关闭优化 /Od (Od的意思:Optimization Disabled ),这样就可以查看到不优化而不会删除了无用逻辑后的汇编是怎么样的。

VS 调试数据

调试->窗口-> 都可以查看:

  • 模块:该进程以加载模块(都是一些已经加载的哪些库)
  • 进程:当前相关进程
  • 内存:当前机器内存(在配合反汇编调试、查看数据是很有用的)
  • 反汇编:就是我们上面提到的
  • 寄存器:可以查看当前寄存器的数据状态(在配合反汇编调试、查看数据是很有用的)
    在这里插入图片描述

模块

在这里插入图片描述
可查看到使用了的各种动态链接的文件

进程

在这里插入图片描述

内存

在这里插入图片描述

这里的内存查看应该是此程序进程的逻辑内存地址(即:进程内存段+逻辑内存地址,来寻址的)

寄存器

在这里插入图片描述
寄存器中,可以查看CPU算术寄存器,段寄存器,浮点寄存器,等。

在内存中的一些字符表信息

如果我们在程序中列出一些常量字符串,然后我们还可以用附加该.exe程序进程后调式(就是断点调试该程序),查看内存可以看到一些字符表的信息,如下,我定位查找在程序中明文使用了Hello world!,然后根据字符串变量指向的常量地址,再通过上面介绍的内存来定位(Hello world!在下面内容中第三行),该字符的地址的前前后后也查找到了其他的一些字符串表的内容,这些字符串应该是编译、链接、合并其他的程序内带上的字符表。

Stack around the variable '.' was corrupted.
The variable '..' is being used without being initialized
Hello world!The value of ESP was not properly saved across a function call.This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling onventionA cast to a smaller data type has caused a loss of data.  If this was intentional, you should mask the source of the cast with the appropriate bitmask.For example:char c = (i & 0xFF);Changing the code in this way will not affect the quality of the resulting optimized code
Stack memory was corrupted
A local variable was used before it was initialized
Stack memory around _alloca was corrupted
Unknown Runtime Check Error.
R.u.n.t.i.m.e. .C.h.e.c.k. .E.r.r.o.r.......
U.n.a.b.l.e. .t.o. .d.i.s.p.l.a.y. .R.T.C. .M.e.s.s.a.g.e.
R.u.n.-.T.i.m.e. .C.h.e.c.k. .F.a.i.l.u.r.e.
#.%.d. .-. .%.s
Unknown Filename
Unknown Module Name
Run-Time Check Failure #%d - %s
Stack corrupted near unknown variable
%.2X 
Stack area around _alloca memory reserved by this function is corrupted
Data:Allocation number within this function:Size:Address:Stack area around _alloca memory reserved by this function is corruptedA variable is being used without being initialized tack pointer corruptionCast to smaller type causing loss of dataStack memory corruptionLocal variable used before initializationStack around _alloca corrupted..

编译出来的ASM文件通常包含的数据

了解我们编译出来的到底是什么文件,首先先了解,我们平时用gcc/g++或是MSVC cl等编译器来编译源文件时,是怎么个步骤:

  • Pre-Processing : 预编译的处理,就是对一些#define开头的宏展开,#include 文件引入到对应位置,或是预编译指令处理:#if #ifdef #ifndef #elif #else #endif 等,但是#pragma会保留不处理,这是编译器要处理的编译指令
  • Compilation : 编译,对预编译后的所有源文件开是编译处理:词法分析、语法分析、语义分析、生成中间代码、中间代码优化(可选)
  • Assembly :
  • Links

编译出来的文件与Window PE(Portable Executable:便携式可执行的),Linux ELF(Executable Linkable Format:可执行可链接的格式)有几分相似,他们都是COFF(Common File Format:公共文件格式)格式之一。

基本分段/分块

  • 代码区 - 在反汇编代码中的:_TEXT SEGMENT ... _TEXT ENDS之间
  • 数据区
    • 全局已初始化区:_DATA SEGMENT ... _DATA ENDS 之间
    • 全局未初始化区:_BSS SEGMENT ... _BSS ENDS 之间
    • 常量区:CONST SEGMENT ... CONST ENDS 之间

以上的这些定义区块,可以在 VSC 或是 Sublime 在使用正则快速搜索,写了个正则为:

  • 通用格式:(\w*)\W*?SEGMENT[\w\W]*?\1\W*?ENDS
    • 查找:_TEXT代码区块:(_TEXT)\W*?SEGMENT[\w\W]*?\1\W*?ENDS
    • 查找:_DATA 全局已初始化区:(_DATA)\W*?SEGMENT[\w\W]*?\1\W*?ENDS
    • 查找:_BSS 全局未初始化区:(_BSS)\W*?SEGMENT[\w\W]*?\1\W*?ENDS
    • 查找:CONST 常量区:(CONST)\W*?SEGMENT[\w\W]*?\1\W*?ENDS

但是上面的正则在 Release 搜索不完整,因为 Release 下有些区块标记会的 XXX SEGMENT会忽略掉,在下面列出的 Release 的反汇编可以看到。但也不影响我们理解这些概念。

这些区块或叫:分段数据,每一个编译出来的文件都会有的,然后他们不同文件最终会链接合并(能直接合并在一块的都是静态链接库)为一个:目标文件(库、可执行文件等)

所以目标文件一般是多个静态库其他的编译文件合并的文件,动态链接就不一样了,它是编译时有检测,运行时才重定位使用到的动态库:函数或数据的地址

反汇编实例

就已字符常量区为例,我们用一段示例C++程序:

// jave.lin - test for deassembly code
int s_i = 999; // static_int
int s_i1 = 0xff001122;
float s_f_ui; // static_float, un initialize 未初始化
float s_f1 = 0.888; // static_floatconst int c_i = 1000; // const int,不在常量区
const float c_f = 0.333; // const float
const char* c_str_ui; // const char*, un initialize
const char* c_str = "This is Global const str."; // const char*int main()
{const char *l_c_str_helloworld = "Hello world!"; // local const string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量const char* l_c_str_second = "This is Seconds const str."; // local const string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量char l_d_str_thrid[50] = "This is Thrid dynamic str."; // local dynamic string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量l_d_str_thrid[0] = '#'; //明文编写字符不会有常量,因为当做一个byte字节数据来处理int l_i = s_i; // local int = static intint l_i1 = s_i1; // local int = static intint l_f_ui = s_f_ui; // local float = static floatint l_f1 = s_f1; // local float = static floatconst int l_c_i = c_i; // local const int = const int,通过反汇编可以看到,c_i被当做立即数使用了,c_i不存在常量区//const int* p_l_c_i = &c_i; // 但是如果有代码使用到c_i的地址,c_i在常量区就会有储存,这是编译器的优化const float l_c_f = c_f; // local const float = const float,通过反汇编可以看到,c_f在常量区有存储,这与const int是有区别的const char* l_c_str_ui = c_str_ui; // local const char* = const char*const char* l_c_str = c_str; // local const char* = const char*return 0;
}

Debug下的反汇编

下面可以查看刚刚上面说的对应区块内容

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.25.28614.0 TITLE	D:\jave\Work Files\CPP\dasm\DASM\DASM\DASM.cpp.686P.XMMinclude listing.inc.model	flatINCLUDELIB MSVCRTD
INCLUDELIB OLDNAMESPUBLIC	?s_i@@3HA					; s_i
PUBLIC	?s_i1@@3HA					; s_i1
PUBLIC	?s_f_ui@@3MA					; s_f_ui
PUBLIC	?s_f1@@3MA					; s_f1
PUBLIC	?c_str_ui@@3PBDB				; c_str_ui
PUBLIC	?c_str@@3PBDB					; c_str
PUBLIC	??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@ ; `string'
_BSS	SEGMENT
?s_f_ui@@3MA DD	01H DUP (?)				; s_f_ui
?c_str_ui@@3PBDB DD 01H DUP (?)				; c_str_ui
_BSS	ENDS
msvcjmc	SEGMENT
__3D4FA793_DASM@cpp DB 01H
msvcjmc	ENDS
;	COMDAT ??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@
CONST	SEGMENT
??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@ DB 'This is Global con'DB	'st str.', 00H				; `string'
CONST	ENDS
_DATA	SEGMENT
?s_i@@3HA DD	03e7H					; s_i
?s_i1@@3HA DD	0ff001122H				; s_i1
?s_f1@@3MA DD	03f6353f8r			; 0.888	; s_f1
?c_str@@3PBDB DD FLAT:??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@ ; c_str
_DATA	ENDS
PUBLIC	_main
PUBLIC	__JustMyCode_Default
PUBLIC	??_C@_0N@KNIDPCKA@Hello?5world?$CB@		; `string'
PUBLIC	??_C@_0BL@LGABGNAE@This?5is?5Seconds?5const?5str?4@ ; `string'
PUBLIC	??_C@_0BL@DIJMBJEP@This?5is?5Thrid?5dynamic?5str?4@ ; `string'
PUBLIC	__real@3eaa7efa
EXTRN	@_RTC_CheckStackVars@8:PROC
EXTRN	@__CheckForDebuggerJustMyCode@4:PROC
EXTRN	@__security_check_cookie@4:PROC
EXTRN	__RTC_CheckEsp:PROC
EXTRN	__RTC_InitBase:PROC
EXTRN	__RTC_Shutdown:PROC
EXTRN	___security_cookie:DWORD
EXTRN	__fltused:DWORD
;	COMDAT __real@3eaa7efa
CONST	SEGMENT
__real@3eaa7efa DD 03eaa7efar			; 0.333
CONST	ENDS
;	COMDAT rtc$TMZ
rtc$TMZ	SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ	ENDS
;	COMDAT rtc$IMZ
rtc$IMZ	SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
rtc$IMZ	ENDS
;	COMDAT ??_C@_0BL@DIJMBJEP@This?5is?5Thrid?5dynamic?5str?4@
CONST	SEGMENT
??_C@_0BL@DIJMBJEP@This?5is?5Thrid?5dynamic?5str?4@ DB 'This is Thrid dyn'DB	'amic str.', 00H				; `string'
CONST	ENDS
;	COMDAT ??_C@_0BL@LGABGNAE@This?5is?5Seconds?5const?5str?4@
CONST	SEGMENT
??_C@_0BL@LGABGNAE@This?5is?5Seconds?5const?5str?4@ DB 'This is Seconds c'DB	'onst str.', 00H				; `string'
CONST	ENDS
;	COMDAT ??_C@_0N@KNIDPCKA@Hello?5world?$CB@
CONST	SEGMENT
??_C@_0N@KNIDPCKA@Hello?5world?$CB@ DB 'Hello world!', 00H ; `string'
CONST	ENDS
; Function compile flags: /Odt
;	COMDAT __JustMyCode_Default
_TEXT	SEGMENT
__JustMyCode_Default PROC				; COMDATpush	ebpmov	ebp, esppop	ebpret	0
__JustMyCode_Default ENDP
_TEXT	ENDS
; Function compile flags: /Odtp /RTCsu /ZI
; File D:\jave\Work Files\CPP\dasm\DASM\DASM\DASM.cpp
;	COMDAT _main
_TEXT	SEGMENT
_l_c_str$ = -180					; size = 4
_l_c_str_ui$ = -168					; size = 4
_l_c_f$ = -156						; size = 4
_l_c_i$ = -144						; size = 4
_l_f1$ = -132						; size = 4
_l_f_ui$ = -120						; size = 4
_l_i1$ = -108						; size = 4
_l_i$ = -96						; size = 4
_l_d_str_thrid$ = -84					; size = 50
_l_c_str_second$ = -24					; size = 4
_l_c_str_helloworld$ = -12				; size = 4
__$ArrayPad$ = -4					; size = 4
_main	PROC						; COMDAT; 13   : {push	ebpmov	ebp, espsub	esp, 376				; 00000178Hpush	ebxpush	esipush	edilea	edi, DWORD PTR [ebp-376]mov	ecx, 94					; 0000005eHmov	eax, -858993460				; ccccccccHrep stosdmov	eax, DWORD PTR ___security_cookiexor	eax, ebpmov	DWORD PTR __$ArrayPad$[ebp], eaxmov	ecx, OFFSET __3D4FA793_DASM@cppcall	@__CheckForDebuggerJustMyCode@4; 14   :     const char *l_c_str_helloworld = "Hello world!"; // local const string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量mov	DWORD PTR _l_c_str_helloworld$[ebp], OFFSET ??_C@_0N@KNIDPCKA@Hello?5world?$CB@; 15   :     const char* l_c_str_second = "This is Seconds const str."; // local const string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量mov	DWORD PTR _l_c_str_second$[ebp], OFFSET ??_C@_0BL@LGABGNAE@This?5is?5Seconds?5const?5str?4@; 16   :     char l_d_str_thrid[50] = "This is Thrid dynamic str."; // local dynamic string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量mov	ecx, 6mov	esi, OFFSET ??_C@_0BL@DIJMBJEP@This?5is?5Thrid?5dynamic?5str?4@lea	edi, DWORD PTR _l_d_str_thrid$[ebp]rep movsdmovswmovsbxor	eax, eaxmov	DWORD PTR _l_d_str_thrid$[ebp+27], eaxmov	DWORD PTR _l_d_str_thrid$[ebp+31], eaxmov	DWORD PTR _l_d_str_thrid$[ebp+35], eaxmov	DWORD PTR _l_d_str_thrid$[ebp+39], eaxmov	DWORD PTR _l_d_str_thrid$[ebp+43], eaxmov	WORD PTR _l_d_str_thrid$[ebp+47], axmov	BYTE PTR _l_d_str_thrid$[ebp+49], al; 17   : 
; 18   :     l_d_str_thrid[0] = '#'; //明文编写字符不会有常量,因为当做一个byte字节数据来处理mov	eax, 1imul	ecx, eax, 0mov	BYTE PTR _l_d_str_thrid$[ebp+ecx], 35	; 00000023H; 19   : 
; 20   :     int l_i = s_i; // local int = static intmov	eax, DWORD PTR ?s_i@@3HA		; s_imov	DWORD PTR _l_i$[ebp], eax; 21   :     int l_i1 = s_i1; // local int = static intmov	eax, DWORD PTR ?s_i1@@3HA		; s_i1mov	DWORD PTR _l_i1$[ebp], eax; 22   :     int l_f_ui = s_f_ui; // local float = static floatcvttss2si eax, DWORD PTR ?s_f_ui@@3MAmov	DWORD PTR _l_f_ui$[ebp], eax; 23   :     int l_f1 = s_f1; // local float = static floatcvttss2si eax, DWORD PTR ?s_f1@@3MAmov	DWORD PTR _l_f1$[ebp], eax; 24   :     const int l_c_i = c_i; // local const int = const int,通过反汇编可以看到,c_i被当做立即数使用了,c_i不存在常量区mov	DWORD PTR _l_c_i$[ebp], 1000		; 000003e8H; 25   :     //const int* p_l_c_i = &c_i; // 但是如果有代码使用到c_i的地址,c_i在常量区就会有储存,这是编译器的优化
; 26   :     const float l_c_f = c_f; // local const float = const float,通过反汇编可以看到,c_f在常量区有存储,这与const int是有区别的movss	xmm0, DWORD PTR __real@3eaa7efamovss	DWORD PTR _l_c_f$[ebp], xmm0; 27   :     const char* l_c_str_ui = c_str_ui; // local const char* = const char*mov	eax, DWORD PTR ?c_str_ui@@3PBDB		; c_str_uimov	DWORD PTR _l_c_str_ui$[ebp], eax; 28   :     const char* l_c_str = c_str; // local const char* = const char*mov	eax, DWORD PTR ?c_str@@3PBDB		; c_strmov	DWORD PTR _l_c_str$[ebp], eax; 29   : 
; 30   :     return 0;xor	eax, eax; 31   : }push	edxmov	ecx, ebppush	eaxlea	edx, DWORD PTR $LN5@maincall	@_RTC_CheckStackVars@8pop	eaxpop	edxpop	edipop	esipop	ebxmov	ecx, DWORD PTR __$ArrayPad$[ebp]xor	ecx, ebpcall	@__security_check_cookie@4add	esp, 376				; 00000178Hcmp	ebp, espcall	__RTC_CheckEspmov	esp, ebppop	ebpret	0npad	3
$LN5@main:DD	1DD	$LN4@main
$LN4@main:DD	-84					; ffffffacHDD	50					; 00000032HDD	$LN3@main
$LN3@main:DB	108					; 0000006cHDB	95					; 0000005fHDB	100					; 00000064HDB	95					; 0000005fHDB	115					; 00000073HDB	116					; 00000074HDB	114					; 00000072HDB	95					; 0000005fHDB	116					; 00000074HDB	104					; 00000068HDB	114					; 00000072HDB	105					; 00000069HDB	100					; 00000064HDB	0
_main	ENDP
_TEXT	ENDS
END

Release下的反汇编

Release下的,有些XXX SEGMENT头部标记没了

; Listing generated by Microsoft (R) Optimizing Compiler Version 19.25.28614.0 TITLE	d:\jave\work files\cpp\dasm\dasm\dasm\dasm.cpp.686P.XMMinclude listing.inc.model	flatINCLUDELIB OLDNAMESPUBLIC	??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@ ; `string'
PUBLIC	??_C@_0N@KNIDPCKA@Hello?5world?$CB@		; `string'
PUBLIC	??_C@_0BL@LGABGNAE@This?5is?5Seconds?5const?5str?4@ ; `string'
PUBLIC	??_C@_0BL@DIJMBJEP@This?5is?5Thrid?5dynamic?5str?4@ ; `string'
PUBLIC	?s_i1@@3HA					; s_i1
PUBLIC	?s_f_ui@@3MA					; s_f_ui
PUBLIC	?s_f1@@3MA					; s_f1
PUBLIC	?c_str@@3PBDB					; c_str
PUBLIC	?s_i@@3HA					; s_i
PUBLIC	?c_str_ui@@3PBDB				; c_str_ui
EXTRN	@__security_check_cookie@4:PROC
?s_f_ui@@3MA DD	01H DUP (?)				; s_f_ui
?c_str_ui@@3PBDB DD 01H DUP (?)				; c_str_ui
_BSS	ENDS
?s_i1@@3HA DD	0ff001122H				; s_i1
?s_f1@@3MA DD	03f6353f8r			; 0.888	; s_f1
?c_str@@3PBDB DD FLAT:??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@ ; c_str
?s_i@@3HA DD	03e7H					; s_i
CONST	ENDS
;	COMDAT ??_C@_0BL@DIJMBJEP@This?5is?5Thrid?5dynamic?5str?4@
CONST	SEGMENT
??_C@_0BL@DIJMBJEP@This?5is?5Thrid?5dynamic?5str?4@ DB 'This is Thrid dyn'DB	'amic str.', 00H				; `string'
CONST	ENDS
;	COMDAT ??_C@_0BL@LGABGNAE@This?5is?5Seconds?5const?5str?4@
CONST	SEGMENT
??_C@_0BL@LGABGNAE@This?5is?5Seconds?5const?5str?4@ DB 'This is Seconds c'DB	'onst str.', 00H				; `string'
CONST	ENDS
;	COMDAT ??_C@_0N@KNIDPCKA@Hello?5world?$CB@
CONST	SEGMENT
??_C@_0N@KNIDPCKA@Hello?5world?$CB@ DB 'Hello world!', 00H ; `string'
CONST	ENDS
;	COMDAT ??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@
CONST	SEGMENT
??_C@_0BK@OEHJENGO@This?5is?5Global?5const?5str?4@ DB 'This is Global con'DB	'st str.', 00H				; `string'
CONST	ENDS
PUBLIC	_main
EXTRN	__fltused:DWORD
; Function compile flags: /Ogtp
; File D:\jave\Work Files\CPP\dasm\DASM\DASM\DASM.cpp
;	COMDAT _main
_TEXT	SEGMENT
_main	PROC						; COMDAT; 14   :     const char *l_c_str_helloworld = "Hello world!"; // local const string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量
; 15   :     const char* l_c_str_second = "This is Seconds const str."; // local const string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量
; 16   :     char l_d_str_thrid[50] = "This is Thrid dynamic str."; // local dynamic string,明文编写字符串比较特别,通过反汇编可以看到,右的值都是常量
; 17   : 
; 18   :     l_d_str_thrid[0] = '#'; //明文编写字符不会有常量,因为当做一个byte字节数据来处理
; 19   : 
; 20   :     int l_i = s_i; // local int = static int
; 21   :     int l_i1 = s_i1; // local int = static int
; 22   :     int l_f_ui = s_f_ui; // local float = static float
; 23   :     int l_f1 = s_f1; // local float = static float
; 24   :     const int l_c_i = c_i; // local const int = const int,通过反汇编可以看到,c_i被当做立即数使用了,c_i不存在常量区
; 25   :     //const int* p_l_c_i = &c_i; // 但是如果有代码使用到c_i的地址,c_i在常量区就会有储存,这是编译器的优化
; 26   :     const float l_c_f = c_f; // local const float = const float,通过反汇编可以看到,c_f在常量区有存储,这与const int是有区别的
; 27   :     const char* l_c_str_ui = c_str_ui; // local const char* = const char*
; 28   :     const char* l_c_str = c_str; // local const char* = const char*
; 29   : 
; 30   :     return 0;xor	eax, eax; 31   : }ret	0
_main	ENDP
_TEXT	ENDS
END

Release下的逻辑代码都因为优化删除了。

但是一些全局的变量,和常量在生成的目标文件也是存在的。

删除 JMC 汇编检测代码 - CheckForJustMyCode

编译出来的汇编代码代码可以看到每一个函数调用都有一段__CheckForDebuggerJustMyCode,觉得碍眼也可以通过:项目->属性->配置属性->C/C+±>常规->支持仅我的代码调式:->选“否” 来关闭这些代码的调用。
在这里插入图片描述

上面就是简单介绍一些查看反汇编的内容


栈帧

栈:stack
栈帧: stack frame

简单理解:栈帧 就是 里头的 一帧数据

有些简单或是底层、嵌入式的汇编程序编写,可能没有栈帧(反正就是不使用高级语言编写的程序,有可能一个函数都没调用,都是由基础指令处理的程序,即:没有call),但理论上可以通过一些类似一些 push, pop, mov, jmp,等命令来控制BP(Based Pointer),SP(Stack Pointer),IP(Instruction Pointer)模拟。以此来实现类似的栈帧功能。

但要看懂高级语言的反汇编指令(有call指令调用的),需要了解:栈帧。

关于栈帧的理解可参考:

  • 手把手教你栈溢出从入门到放弃(上)
  • 手把手教你栈溢出从入门到放弃(下)
    • 这个从入门到放弃的上、下篇看完基本对算是栈帧有了一定理解,推荐可以看看,图文都比较清晰
  • 系统栈的工作原理
  • 栈帧(Stack Frame)
  • 百科 - 栈帧
  • 汇编中EBP寄存器和ESP寄存器的区别
  • 栈帧与函数调用过程

看完上面的一些零零散散的文章后,可总结

总结

注意下面描述时,需要区别:栈,栈帧两个不同的概念

  • 系统维护栈,这个栈指针内存对象假设声明为:char *pStack;
  • 与数据结构中的栈差不多的,都是后进先出(后push,先pop)栈内存大小:每个独立进程都有的一份运行需要的栈数据,通常是2M的大小
    • 即:char *pStack = malloc(2 * 1024 * 1024);
    • 然后定义一个栈底指针:char *pStackBased = pStack + (2 * 1024 * 1024); - SBP(Stack Based Pointer)
    • 然后定义一个栈顶指针:*char *pStackTop = pStack; - ESP(与汇编的一样的名字)
    • 由上面的SBP,ESP指向的地址位置,就可以看出此栈与数据结构中的栈不太一样
      • push时,栈顶pStackTop的地址是减少的,在汇编里头一般可以看到:push eax会是push 999,类似下列伪代码:
      • pop时,栈顶 pStackTop 的地址是增加的,在汇编里头一般可以看到:pop ebp,类似下列伪代码:
void push(const data_type data) {*(pStackTop--) = data; // 先放置到sTackTop上,再偏移指针到下一个位置,注意这里的pStackTop是--的,因为这个系统栈的栈底在最高的地址
}
void pop(register_type &register_ref) {register_ref = *(++pStackTop); // 先偏移到上一次栈顶,再取栈顶上存放的数据
}
  • 如果我们的程序调用层次太多,就容易调用栈溢出(假设栈的基地址为:SBP(Stack Based Pointer),即我们前面假设的:pStack,溢出就是:(SBP - ESP) > (2 * 1024 * 1024)),常见的就是我们程序中的无限递归的BUG

栈帧

  • 栈帧是系统维护的内存中的一块内存,只不过它仅仅包含的是某个方法调用时的函数栈帧状态需要的数据,一个栈帧通常包含一些状态数据:EBP、ESP、EIP

EBP, ESP, EIP

  • 栈帧的状态数据范围:就是EBP(高地址)~ESP(底地址)之间的内存数据
    • EBP:Extend Based Pointer,一直指向的是当前栈帧的基地址,也叫栈帧的底,相对ESP来说,EBP是高地址,在整个函数调用的栈帧中是不变的,除非到准备弹出该栈帧时,会设置回上一个栈帧(父级调用函数)的EBP,
    • ESP:Extend Stack Pointer,一直指向的是当前栈帧的顶,相对EBP来说,ESP是底地址,也是一直指向栈的栈顶(注意是栈的栈顶),栈的栈顶与栈帧的栈顶都是相同的,也就说ESP当前会一直指向栈顶,与栈帧顶,与前面介绍栈的ESP一样push、pop都会减少与增加ESP的地址。
    • EIP:Extend Instruction Pointer,一直指向CPU当前准备需要执行的指令指针。asm 函数调用call其中就包含了对EIP定位到指定函数指令首地址(call functionAddress包含两个操作等价于伪代码:(一) push (current eip + size(current cmd)),(二)mov eip, functionAddress

所以一个栈帧的状态需要上面三个数据:EBP,ESP,EIP

那么父函数调用子函数,然后子函数执行完了之后如何恢复回父函数呢?

这句话也可以这么问:

弹出一个栈帧,如何将EBP,ESP,EIP恢复到上一帧的这些数据呢?

答案就是:

在构建新的一个栈帧时,就存有上一帧(上一个函数)的这三个EBP,ESP,EIP数据即可。

所以我们在反汇编代码中可以看到(不开启代码优化)每个函数调用前都用类似下面的码:

示例对应的C++源码:

#include<iostream>
#include<typeinfo>
//#include"my_funcs.h"
int 
//_cdecl 
_stdcall
add(int a, int b, int c)
{int local1 = 0;int local2 = 10;int local3 = 1;long long local4 = 2;return a + b + c + local1 + local2;
}int main() {int a = 1;int b = 2;int c = 3;int d = add(a, b, c);printf("d = %d\n", d);//d = multiply(b, d);//printf("d = %d\n", d);return c;
}

下面是反汇编后add函数前、中、后的处理

调用函数前

在这里插入图片描述

add函数有三个参数,在调用前,都push到栈里,参数入栈的顺序是按:调用约定来决定的。调用约定同时也决定了函数栈帧在恢复到上一个栈帧是在 被调用 函数栈帧中恢复,还是在上一个调用 函数中的栈帧恢复。

调用函数内

在这里插入图片描述

  • push ebp 先将上一个栈帧的 ebp 备份到当前栈顶
  • mov ebp, espesp寄存器的值赋值给ebp寄存器,可理解为:将当前栈顶作为此栈帧的新的ebp
  • sub esp, 14hesp寄存器的值减少 14h,可理解为:分配好此栈帧的内存大小,大小为十六进制的:14h,对应十进制为:20

其他常用寄存器 EAX

  • EAX:Extend Accumulator X,Accumulator是累积、累加的意思,就是一般做运算用的,X代表他是一个通过寄存器的意思。用于栈帧弹出前,将该函数栈帧的返回值设置到EAX,以便恢复到上一个栈帧的下一条指令处理用(如果有返回值的话),下一条命令只要接收EAX寄存器的值就可以了。在反汇编的代码中除了常在在函数结尾返回值对EAX赋值处理,在一般的立即数赋值或是初始化都话看到有此寄存器的频繁使用

call 指令

可参考:“The call instruction pushes the return address onto the stack then jumps to the destination.”
或是看我之前翻译

call functions-address

相当于

push eip+2 ; // 2 是不确定,不通编译器、或是不同编译平台目标的指令处理的下一条指令是不同长度的, eip+2组合就相当于下一条指令的地址,push eip+2就将它备份入栈,返回后续ret指令恢复eip指令地址而使用的备份数据
jump functions-address

ret 指令

可参考:“The ret instruction pops and jumps to the return address on the stack. A nonzero #n in the RET instruction indicates that after popping the return address, the value #n should be added to the stack pointer.” - MS 文档
或是看我之前翻译

简单的描述 ret 指令,相当远下列过程:

ret 后无数值
push ebp
mov ebp, esp
... ; // 无局部变量,所以没有申请栈
ret

相当于

push ebp
mov ebp, esp
...
jump return-address
ret 后有数值的
push ebp
mov ebp, esp
sub esp, 0x0ch ; 分配有12个byte的局部变量的空间
...
ret 0x0ch ; 0x0ch == 12

相当于

push ebp
mov ebp, esp
sub esp, 0x0ch ; 分配有12个byte的局部变量的空间
...
add esp, 0x0ch ; 12 个 byte的局部变量的空间清理
jump return-address

有了前面了解:call、ret指令后,就可以了解:调用函数末端-返回-清理栈

调用函数末端-返回-清理栈

_stdcall

在这里插入图片描述

_stdcall 调用约定中就指令在callee中清理参数压栈的空间

_cdecl

在这里插入图片描述
_cdecl 调用约定中没有清理

因为_cdecl是在caller中清理参数压栈的空间
在这里插入图片描述

在_cdecl 中,push三个int,每个int 占4 个byte,一个12个,十六进制就是0x0ch,在caller中add esp, 0ch删除参数压栈的空间(所以这样时为何_cdecl可以处理变长参数,因为在caller压栈所少个是知道的,在caller再根据数量清理即可)

References

  • 寄存器(cpu工作原理) - 转载于王爽的《汇编语言》PPT
  • ARM汇编指令集汇总 - 嵌入式芯片指令(ARM)
  • VC6.0和VS2005查看查看C或者C++文件汇编代码的方法
  • vs下查看汇编代码
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 数据库(MYSQL-SQL分组函数)

    select avg(A),min(A)-from table-where A like %D%...

    2024/4/24 7:35:21
  2. windows---mysql5.7定时备份

    创建一个脚本:@echo off set "Ymd=%date:~,4%%date:~5,2%%date:~8,2%%time:~0,2%%time:~3,2%%time:~6,2%" cd D:\phpStudy\MySQL\bin\ mysqldump --opt --single-transaction=TRUE --user=root --password=root --host=127.0.0.1 --protocol=tcp --port=3306 --defa…...

    2024/4/24 7:35:10
  3. 使用C#操作Excel(读写包含wps)

    转发https://www.cnblogs.com/kenjiang/p/10790652.htmlC#读写Excel的几种方法1 使用Office自带的库前提是本机须安装office才能运行,且不同的office版本之间可能会有兼容问题,从Nuget下载 Microsoft.Office.Interop.Excel读写代码如下:1 using Microsoft.Office.Interop.Ex…...

    2024/4/24 7:35:16
  4. 用AI改变传统招聘模式:看人工智能是如何改变招聘实践的?

    人工智能是当今技术讨论的重中之重。该领域的进步已经改变了传统上的工作方式。让我们以招聘过程为例。来看看我们实施人工智能,可以在招聘活动中有哪些新内容? 说人工智能正在与人力资源一起工作似乎是矛盾的,但是几乎80%的高管认为人工智能可以提高他们的整体生产力和性能…...

    2024/4/24 7:35:09
  5. 【SQL数据库笔记】手机的前三位后四位快速检索客户信息,数据库中匹配中间四位,数据库存储过程代码

    使用存储过程示例代码:declare @No1 varchar(20)--- declare @NO2 varchar(20)--- select @No1=CardID from CardInfo where customerID in (select customerID from userInfo where customerName=李四) select @No2=CardID from CardInfo where customerID in (select cust…...

    2024/4/24 7:35:07
  6. JS笔记02-数组

    创建一维数组:方法1 var arr=[元素1,元素2......] 其实也可以这样创建空数组 var arr=[]; 方法2 var arr=new Array();指定访问某个元素:数组名[下标号], 下标号默认是从0 开始编号js的数组可以动态的增长;js中,通过一个函数传递数组,默认是引用传递遍历数组for(var i=0;i…...

    2024/4/24 7:35:05
  7. javasejavase基础篇学习之接口

    关键字: interface jdk8以后 除了抽象方法,还允许有普通方法 普通方法前需加default 可重写也可以不重写 新特性还有静态方法...

    2024/4/24 7:35:05
  8. tensorflow中RMSprop优化器运用

    tensorflow中RMSprop优化器运用RMSprop优化器引用API:tf.keras.optimizers.RMSprop代码实现:#RMSpropbeta = 0.9 #定义超参数,经验值为0.9v_w = beta * v_w + (1 - beta) * tf.square(grads[0]) #求二阶动量v_wv_b = beta * v_b + (1 - beta) * tf.square(grads[1]) #求二阶…...

    2024/4/16 19:33:44
  9. week13作业

    C - TT 的奖励(必做)解题思路: 对于这道题目来讲,感觉算是一道比较经典的dp问题,但是,自己一开始没有想到利用dp解决,在这一点上,说明自己对于dp的问题感触不够深。当看到这道题目时,首先出现在自己脑海中的是之前做过的两道题目——即宇宙射线问题与矩阵选数问题,总…...

    2024/4/16 19:33:44
  10. spring boot项目中验证码功能实现

    写spring boot项目登录功能是,验证码功能肯定是不能少的,这里将介绍一个工具来生成二维码,kaptchaKaptcha使用步骤导入jar包编写Kaptcha配置类生成随机字符串和验证码图片 导入jar包<dependency><groupId>com.github.penggle</groupId><artifactId>…...

    2024/4/16 19:33:32
  11. 几何问题中的分治法

    几何问题中的分治法 1.最近对问题 问题描述:设p1=(x1,y1),p2=(x2,y2),…,pn=(xn,yn)一共n个点构成点集S,最近点对问题就是找出集合中距离最近的两个点,严格来说最近点对可能多于一个,但我们简单起见只找出一对即可。算法思路:(1)划分:将集合S分成两个子集S1和S2,根据平衡子…...

    2024/4/19 17:17:20
  12. Java Web 笔记

    JAVA WEB笔记通信结构HTML基础JSP(Java Server Pager)JSP基本元素注释 通信结构 C/S(客户机/服务器)将APP下载到PC与Server通信 B/S(浏览器/服务器): 用户输入—>PC—>向Web Server发送请求—>Web Server访问数据库服务器—>数据库服务器向Web Server返回结果…...

    2024/4/24 7:35:03
  13. android开发之相对布局

    android开发之相对布局关键词代码展示成果展示 关键词 RelativeLayut(相对布局);centerInParent(相对父元素居中);above(相对目标元素向上);below(相对目标元素向下) 代码展示成果展示...

    2024/4/24 7:35:05
  14. Qt文档阅读笔记-重现GUI事件进行单元测试

    主要的逻辑是,存储Widget事件,然后在Test中重放如下,在私有槽函数中测试函数如果要加模拟,需要在后面添加_data()class TestGui: public QObject {Q_OBJECTprivate slots:void testGui_data();void testGui(); };下面的代码中,QTest::addColumn为添加列,第一个为重现的事…...

    2024/4/24 7:35:01
  15. Jupyter notebook:由于GPU内存不足的原因,可能导致的错误提示

    1、Failed to get convolution algorithm. This is probably because cuDNN failed2、tensorflow:OOM when allocating tensor with shape[225,256,256,36] and type float on /job:localhost/re解决办法:1.减少卷积核的数量2.减小输入图像的尺寸3.减少输入图像批次的大小4.关…...

    2024/4/24 7:35:02
  16. 初识focal loss

    意义 消除正负样本不平衡的问题,主要应用于one-stage的任务中,由于正样本(目标)在图像中的比重远远低于负样本(背景),经过NMS后还是会存在大量的负样本,这样会使得负样本占LOSS的比重远大于正样本,LOSS可能会朝着负样本的方向优化。一个极端的例子,如果数据中只有一个…...

    2024/4/24 7:35:06
  17. 论文阅读笔记《Image Deformation Meta-Networks for One-Shot Learning》

    核心思想本文是通过数据增强的形式实现小样本学习任务,采取的方式比较直接,通过对图片进行变形来实现数据集的扩充。作者首先为我们展示了一组图片,如下图所示可以看到上述图片虽然经过了多种变形(如虚化,拼接,遮挡),但由于依旧保留了重要的语义信息,我们还是非常容易…...

    2024/4/24 7:34:58
  18. 微信开发---授权登录

    记录下微信开发遇到的遇到的几种授权,待继续填充一 开放平台-网站应用详情阅读 官方文档1.1 获取授权 access_token 以及标识 openid 。method: geturl: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=auth…...

    2024/4/24 7:34:57
  19. 数据比较与同步工具Syncnavigator|数据比较与同步工具下载|数据库实时同步

    SyncNavigator v8.6.2SyncNavigator是一款功能强大的数据库同步软件,适用于SQL SERVER, MySQL,具有自动/定时同步数据、无人值守、故障自动恢复、同构/异构数据库同步、断点续传和增量同步等功能,支持Windows xp以上所有操作系统,适用于大容量数据库快速同步。安装包下载地…...

    2024/4/29 1:16:39
  20. c++变量与基本类型 (细节)

    c++变量与基本类型 (细节) (解决面试时常问的考点以及易忘点易混点) 一些经验准则:如果明确数值不为负,则选择无符号类型 使用int执行整数运算(如果超出int数值范围则采用 long long) 执行浮点数运算采用double(注意double类型不可以用==判断相等,可以用相差值小于一个很小的…...

    2024/4/24 7:34:55

最新文章

  1. 请求接口报错:java.lang.IllegalStateException: argument type mismatch

    目录 一、场景二、报错信息三、控制器四、接口调用五、原因六、解决 一、场景 1、调用后端接口报错 2、接口参数以Json方式传递 – 二、报错信息 java.lang.IllegalStateException: argument type mismatch Controller [com.xxx.huarunshouzheng.controller.MallControlle…...

    2024/5/1 5:15:23
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 第十二届蓝桥杯省赛真题(C/C++大学B组)

    目录 #A 空间 #B 卡片 #C 直线 #D 货物摆放 #E 路径 #F 时间显示 #G 砝码称重 #H 杨辉三角形 #I 双向排序 #J 括号序列 #A 空间 #include <bits/stdc.h> using namespace std;int main() {cout<<256 * 1024 * 1024 / 4<<endl;return 0; } #B 卡片…...

    2024/5/1 3:56:21
  4. C# 构建可定时关闭的异步提示弹窗

    C# 构建可定时关闭的异步提示弹窗 引言1、调用接口的实现2、自动定时窗口的实现 引言 我们在最常用最简单的提示弹框莫过于MessageBox.Show( )的方法了&#xff0c;但是使用久了之后&#xff0c;你会发现这个MessageBox并不是万能的&#xff0c;有事后并不想客户去点击&#x…...

    2024/4/30 2:59:02
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/29 23:16:47
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57