基于x86_64汇编语言简单教程6: 变量,常量,与运算
目录
变量
为未初始化的数据分配存储空间
多重初始化
常量
equ指令
%assign 指令
%define指令
算数指令
inc 自增指令
dec指令
ADD和SUB指令
imul/mul和idiv/div
实践:我们来写一个简单的一位数加法器
NASM逻辑指令
AND 指令
OR 指令
XOR 指令
TEST 指令
NOT 指令
实践:测试一个数是技术还是偶数
变量
我们下面来聊一聊变量这个概念。NASM提供了各种定义指令来为变量保留存储空间。define assembler指令用于分配存储空间。它可以用于保留以及初始化一个或多个字节。
var_name dw 1234, 2345, ...
这就是一个经典的定义变量的方式。当然,dw可以换成这些内容:
指令 | 目的 | 储存空间 |
---|---|---|
DB | 定义字节 | 分配1个字节 |
DW | 定义字 | 分配2个字节 |
DD | 定义双字 | 分配4个字节 |
DQ | 定义四字 | 分配8个字节 |
DT | 定义十个字节 | 分配10个字节 |
-
字符的每个字节均以十六进制形式存储为其ASCII值。
-
每个十进制值都将自动转换为其等效的16位二进制数,并以十六进制数形式存储。这是在预处理阶段就做好的!
-
处理器使用小尾数字节顺序。
-
负数将转换为其2的补码表示形式。
-
短浮点数和长浮点数分别使用32位或64位表示。
为未初始化的数据分配存储空间
reserve指令用于为未初始化的数据保留空间。reserve指令采用单个操作数,该操作数指定要保留的空间单位数。每个define指令都有一个相关的reserve指令。
指令 | 目的 |
---|---|
RESB | 保留一个字节 |
RESW | 保留字 |
RESD | 保留双字 |
RESQ | 保留四字 |
REST | 保留十个字节 |
多重初始化
TIMES指令允许多次初始化为相同的值。例如,可以使用以下语句定义一个大小为9的标记的数组并将其初始化为零-
marks TIMES 9 DW 0
常量
NASM提供了几个定义常量的指令。在前面的章节中,我们已经使用过EQU指令。我们将特别讨论三个指令-
-
equ
-
%assign
-
%define
equ指令
equ指令用于定义常量。EQU指令的语法如下-
CONSTANT_NAME EQU expression
TOTAL_STUDENTS equ 50
然后,您可以在代码中使用此常量值,例如
mov ecx, TOTAL_STUDENTS cmp eax, TOTAL_STUDENTS
equ语句的操作数可以是表达式-
LENGTH equ 20 WIDTH equ 10 AREA equ length * width
%assign 指令
在%assign 指令可以用来定义数字常量像EQU指令。该指令允许重新定义。例如,您可以将常量TOTAL定义为-
%assign TOTAL 10
在代码的后面,您可以将其重新定义为-
%assign TOTAL 20
注意 - 指令区分大小写。
%define指令
在 %define 指令允许定义数值和字符串常量。该指令类似于C中的#define。例如,您可以将常量PTR定义为-
%define PTR [EBP+4]
上面的代码用[EBP + 4]替换了PTR。
该指令还允许重新定义,并且区分大小写。
算数指令
我们知道,存储的数据必须能够被运算,这才有意义。我们下面来看看一些常见的运算指令。
inc 自增指令
inc指令(increase)用于将操作数加1。它对可以在寄存器或内存中的单个操作数起作用。
; 完全等价于 t++, 在C编译器就会翻译成inc指令 inc destination
目标操作数可以是8位,16位或32位操作数。
INC EBX ; 32-bit 寄存器 自增1 INC DL ; 8-bit 寄存器 自增1 INC [count] ; 变量count 自增1
dec指令
dec(decline)指令实际上就是对操作数-1,inc指令类似!
DEC destination
ADD和SUB指令
ADD和SUB指令用于对字节,字和双字大小的二进制数据进行简单的加/减,即分别用于添加或减去8位,16位或32位操作数。ADD和SUB指令具有以下语法
ADD/SUB destination, source
ADD / SUB指令可以发生用在
-
寄存器
->
寄存器 -
内存
->
寄存器 -
寄存器
->
内存 -
寄存器
->
常量数据 -
内存
->
常量数据
但是,像其他指令一样,使用ADD / SUB指令也无法进行存储器到存储器的操作。ADD或SUB操作设置或清除溢出和进位标志。也就是说,我们可以直接因此而检查EFLAGS完成一些条件动作。
imul/mul和idiv/div
mul
指令用于无符号整数的乘法,处理时,通常被乘数在 EAX
中,而乘数可以是任何寄存器或内存位置。乘法的结果会存储在 EDX:EAX
中,EAX
保存低32位结果,EDX
保存高32位结果。这种设计是为了处理可能超出32位的乘法结果。例如,若 EAX
存储值 5,EBX
存储值 3,执行 mul ebx
后,EAX
将变为 15,EDX
将为 0,表示没有高位。
imul
指令也用于乘法,但支持有符号整数。与 mul
不同,imul
可以接受一个或两个操作数。如果只有一个操作数,imul
会将该操作数与 EAX
相乘,结果仍然存储在 EDX:EAX
中。如果有两个操作数,第一个操作数通常在 EAX
中,第二个是乘数。例如,如果 EAX
中存储 -5,执行 imul eax, 3
后,EAX
将变为 -15。使用两个操作数时,如果 EAX
是 -5,EBX
是 3,执行 imul ebx
后,EAX
也会变为 -15。
情况 | 描述 |
---|---|
当两个字节相乘时 | 被乘数在AL寄存器中,而乘数在存储器或另一个寄存器中为一个字节。结果放到AX。乘积的高8位存储在AH中,低8位存储在AL中。 |
当两个单字值相乘时 | 被乘数应位于AX寄存器中,并且乘数是内存或其他寄存器中的一个字。例如,对于MUL DX之类的指令,必须将乘数存储在DX中,将被乘数存储在AX中。结果乘积是一个双字,将需要两个寄存器。高阶(最左侧)部分存储在DX中,而低阶(最右侧)部分存储在AX中。 |
当两个双字值相乘时 | 当两个双字值相乘时,被乘数应位于EAX中,并且该乘数是存储在存储器或另一个寄存器中的双字值。生成的乘积存储在EDX:EAX寄存器中,即,高32位存储在EDX寄存器中,低32位存储在EAX寄存器中。 |
在除法方面,div
用于无符号整数的除法。被除数是 EDX:EAX
,因此在执行之前,通常需要将 EDX
清零,以避免意外的高位影响。除数可以是寄存器或内存,执行后,商将存储在 EAX
中,余数存储在 EDX
中。例如,如果 EAX
是 15,EBX
是 3,执行 div ebx
后,EAX
将变为 5,而 EDX
将为 0,表示没有余数。
idiv
用于有符号整数的除法,其操作方式与 div
类似,被除数依然是 EDX:EAX
。同样,在执行之前,EDX
需要被清零,以确保结果正确。商存储在 EAX
中,余数存储在 EDX
中。如果 EAX
是 -15,而 EBX
是 3,执行 idiv ebx
后,EAX
将变为 -5,EDX
将为 0。idiv
可以处理负数,正确计算出符号。
情况 | 描述 |
---|---|
当除数为1个字节时 | 假定被除数位于AX寄存器(16位)中。除法后,商进入AL寄存器,其余部分进入AH寄存器。 |
当除数为1个单字时 | 假定分红为DX:AX寄存器中的32位长。高位16位在DX中,低位16位在AX中。除法后,16位的商进入AX寄存器,而16位的余数进入DX寄存器。 |
当除数是双字 | 假定在EDX:EAX寄存器中分红为64位长。高阶32位在EDX中,低阶32位在EAX中。除法后,32位的商进入EAX寄存器,而32位的余数进入EDX寄存器。 |
实践:我们来写一个简单的一位数加法器
为了方便起见,我们来尝试写一个一位数的加法器试试看。
> ./result Input your first digit:> 1 Input your second digit:> 2 the result is:> 3 >
请写一个程序,完成上面的动作。下面是一些提示:
首先,你需要至多三个变量,两个存储输入,一个存储输出。笔者出于编程效率,选择三个变量!省事!
从键盘获取到的是ASCII字符,你需要做点转换!
输出的时候,记得也需要是ASCII字符,否则你会发现你的控制台啥也没有~
写好了?答案揭晓:
; -------------------------------------------------- ; Program written in 10.20 2024 ; Author: Charlie chen ; Functionality: Make Add for digit! ; --------------------------------------------------; help announce a typical string %macro ANNOUNCE_STRING 2%1 db %2%1_LEN equ $ - %1 %endmacro; fast use of common value %define MY_STDOUT 1 %define MY_SYS_WRITE 4 %define MY_STDIN 0 %define MY_SYS_READ 3; print string in a simple way %macro PRINT_STRING 2mov edx, %2mov ecx, %1mov ebx, MY_STDOUTmov eax, MY_SYS_WRITEint 0x80 %endmacro%macro EASY_PRINT_STRING 1PRINT_STRING %1, %1_LEN %endmacro; exit program %macro EXIT 0mov ebx, 0mov eax, 1int 0x80 %endmacro; transfer from ascii to value %macro GAIN_NUMBER 1mov al, [%1]sub al, '0'mov [%1], al %endmacro; read ascii from console %macro READ_SINGLE_BYTE_FROM_CONSOLE 1mov edx, 2mov ecx, %1mov ebx, MY_STDINmov eax, MY_SYS_READint 0x80 %endmacro%macro PRINT_SLASH 0mov edx, 1mov ecx, SLASHmov ebx, MY_STDOUTmov eax, MY_SYS_WRITEint 0x80 %endmacrosection .dataANNOUNCE_STRING TELL_INPUT_NUM_1, "Input your first digit:> "ANNOUNCE_STRING TELL_INPUT_NUM_2, "Input your second digit:> "ANNOUNCE_STRING RESULT_STR, "the result is:> "SLASH db 0xAsection .bssnum_1 resb 2 ; other byte for \nnum_2 resb 2 ; other byte for \nresult resb 1section .textglobal _start _start:EASY_PRINT_STRING TELL_INPUT_NUM_1READ_SINGLE_BYTE_FROM_CONSOLE num_1EASY_PRINT_STRING TELL_INPUT_NUM_2READ_SINGLE_BYTE_FROM_CONSOLE num_2GAIN_NUMBER num_1GAIN_NUMBER num_2mov eax, [num_1]add eax, [num_2]add eax, '0'mov [result], eaxEASY_PRINT_STRING RESULT_STRPRINT_STRING result, 1PRINT_SLASHEXIT
NASM逻辑指令
处理器指令集提供指令AND,OR,XOR,TEST和NOT布尔逻辑,它们根据程序的需要测试,设置和清除位。
指令 | 格式 |
---|---|
AND | AND 操作数1,操作数2 |
OR | OR 操作数1,操作数2 |
XOR | XOR 操作数1,操作数2 |
TEST | TEST 操作数1,操作数2 |
NOT | NOT 操作数1 |
在所有情况下,第一个操作数都可以在寄存器或内存中。第二个操作数可以是寄存器/内存,也可以是立即数(常数)。但是,内存到内存操作是不可能的。这些指令比较或匹配操作数的位,并设置CF,OF,PF,SF和ZF标志。
AND 指令
AND 指令用于通过执行按位AND运算来支持逻辑表达式。如果两个操作数的匹配位均为1,则按位AND运算返回1,否则返回0。它可用于清除一个或多个位。例如,假设BL寄存器包含00111010。如果您需要将高阶位清除为零,则将其与0FH进行“与”运算。
AND BL, 0FH ; This sets BL to 0000 1010
让我们来看另一个例子。如果要检查给定数字是奇数还是偶数,一个简单的测试将是检查数字的最低有效位。如果为1,则数字为奇数,否则为偶数。
假设数字在AL寄存器中,我们可以写-
and al, 01H ; ANDing with 0000 0001 jz tell_is_even_number
OR 指令
OR 指令用于通过执行按位或运算来支持逻辑表达式。如果来自任何一个或两个操作数的匹配位为1,则按位OR运算符将返回1。如果两个位均为零,则返回0。
或运算可用于设置一个或多个位。例如,假设AL寄存器包含0011 1010,则需要设置四个低阶位,您可以将其与值0000 1111(即FH)进行或运算。
OR BL, 0FH ; This sets BL to 0011 1111
下面的示例演示OR指令。让我们将值5和3分别存储在AL和BL寄存器中,然后是指令,
OR AL, BL
XOR 指令
XOR 指令实现按位XOR运算。当且仅当来自操作数的位不同时,XOR运算将结果位设置为1。如果来自操作数的位相同(均为0或均为1),则将结果位清除为0。将操作数与自身进行XOR会将操作数更改为0。这用于清除寄存器。
XOR EAX, EAX
TEST 指令
TEST 指令与AND运算的工作原理相同,但与AND指令不同的是,它不会更改第一个操作数。因此,如果我们需要检查寄存器中的数字是偶数还是奇数,我们也可以使用TEST指令执行此操作,而无需更改原始数字。
TEST AL, 01H JZ EVEN_NUMBER
NOT 指令
NOT 指令实现按位NOT运算。NOT操作将操作数中的位取反。操作数可以在寄存器中,也可以在存储器中。
Operand1: 0101 0011 After NOT -> Operand1: 1010 1100
实践:测试一个数是技术还是偶数
现在,你需要测试一个4位数是技术还是偶数:
charliechen@Charliechen:~/demo/demo9$ ./result Input your first digit:> 1234 the result is that the number: 1234 is even
老样子,先写,我给一些提示:
这是超前的:你可以使用jmp跳转到一个标签,我来写一个简单的范例:
... section .dataANNOUNCE_STRING WORK_FLOW_STR, {"Workflow here!", 0xA}section .textglobal _start _RunFlow_here:EASY_PRINT_STRING WORK_FLOW_STRjmp _exit_start:jmp _RunFlow_here _exit:EXITcharliechen@Charliechen:~/demo/demo9$ ./result Workflow here!可以看到我们可以使用jmp指令在标签之间跳转执行,是的,这就是goto的原型!
回到开头,你可以是用test或者是and,然后使用JZ或者是JNZ来完成跳转。
写好了?答案揭晓:
; -------------------------------------------------- ; Program written in 10.20 2024 ; Author: Charlie chen ; Functionality: test if a number is even or odd ; --------------------------------------------------; help announce a typical string %macro ANNOUNCE_STRING 2%1 db %2%1_LEN equ $ - %1 %endmacro; fast use of common value %define MY_STDOUT 1 %define MY_SYS_WRITE 4 %define MY_STDIN 0 %define MY_SYS_READ 3; print string in a simple way %macro PRINT_STRING 2mov edx, %2mov ecx, %1mov ebx, MY_STDOUTmov eax, MY_SYS_WRITEint 0x80 %endmacro%macro EASY_PRINT_STRING 1PRINT_STRING %1, %1_LEN %endmacro; exit program %macro EXIT 0mov ebx, 0mov eax, 1int 0x80 %endmacro; read ascii from console %macro READ_FROM_CONSOLE 2mov edx, %2mov ecx, %1mov ebx, MY_STDINmov eax, MY_SYS_READint 0x80 %endmacro%define NUM_LIMIT_MAX 5section .dataANNOUNCE_STRING TELL_INPUT_NUM, "Input your first digit:> "ANNOUNCE_STRING RESULT_STRING, "the result is that the number: "ANNOUNCE_STRING ODD_STRING, {" is odd!", 0xA}ANNOUNCE_STRING EVEN_STRING, {" is even", 0xA}section .bssnum resb NUM_LIMIT_MAX ; other byte for \nsection .textglobal _start_tell_is_even:EASY_PRINT_STRING EVEN_STRINGjmp _to_exit_tell_is_odd:EASY_PRINT_STRING ODD_STRINGjmp _to_exit_to_exit:EXIT_start:EASY_PRINT_STRING TELL_INPUT_NUMREAD_FROM_CONSOLE num, NUM_LIMIT_MAXmov eax, dword [num]sub eax, '0'test al, 0x1EASY_PRINT_STRING RESULT_STRINGPRINT_STRING num, 4jz _tell_is_oddjmp _tell_is_even
相关文章:
基于x86_64汇编语言简单教程6: 变量,常量,与运算
目录 变量 为未初始化的数据分配存储空间 多重初始化 常量 equ指令 %assign 指令 %define指令 算数指令 inc 自增指令 dec指令 ADD和SUB指令 imul/mul和idiv/div 实践:我们来写一个简单的一位数加法器 NASM逻辑指令 AND 指令 …...

Vue-router 路由守卫执行流程图
vue-router 路由守卫执行的流程图(个人理解) 图1 - 图2...
ES6 中函数参数的默认值
概述: ES 允许给函数的参数赋初始值; 代码示例及相关说明: <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>函数参数默认值</title> </head> <body> <script&g…...
Redis知识应用索引指南
Redis,全称为Remote Dictionary Server,是一个开源的高性能键值对数据库。它以其卓越的性能、丰富的数据结构和灵活的持久化机制,在现代应用中扮演着至关重要的角色 1 什么是redis Redis是一个使用ANSI C语言编写的开源、跨平台的键值存储系…...

ES6扩展运算符
1.介绍: ... 扩展运算符能将数组转换为逗号分隔的参数序列; 扩展运算符(spread)也是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的 参数序列,对数组进…...
【树莓派 5B】Python 版本切换
【树莓派 5B】Python 版本切换 前言整体思路具体步骤常见问题Python 无法建立与 Python3 的软连接 前言 本文基于树莓派5B 32-bit 树莓派OS,以 Python-3.11.2 降级到 3.9.2 为例,总结了在树莓派上切换 Python 版本的步骤,帮助大家轻松完成 P…...
windows C++-有效使用PPL(五)
如果可能,避免错误共享 当在不同处理器上运行的多个并发任务写入位于同一高速缓存行上的变量时,会发生错误共享。 当一个任务写入一个变量时,这两个变量的缓存行将会失效。 每当缓存行失效时,每个处理器必须重新加载缓存行。 因此…...

【排序】——1.冒泡排序法(含优化)
冒泡排序 1.原理 左边大于右边交换一趟排下来最大的交换到右边来(接下来所以文章用升序举例) 从左到右,相邻元素进行比较。 每次比较一轮,就会找到序列中最大的一个(最小的一个——降序)。这个数就会从序列的最右边冒出来。 以…...
在MySQL中创建数据库和表
在MySQL中,创建数据库和表是数据库管理的基础操作。下面我将详细解释如何先创建一个数据库,然后在该数据库中创建一个或多个表。 ### 1. 创建数据库 首先,你需要登录到MySQL服务器。然后,使用CREATE DATABASE语句来创建一个新的…...

Hadoop 安装教程——单节点模式和分布式模式配置
文章目录 一、预备知识1.1 Hadoop 发行版本1.2 部署方式 二、预备条件2.1 环境准备2.2 创建新用户(可选)2.3 配置 SSH 无密码登录2.4 下载 Hadoop2.5 编辑 hadoop-env.sh 脚本2.6 编辑 dfs 和 yarn 脚本 三、单节点模式部署3.1 官方使用案例3.2 查看运行结果 四、伪分布模式部署…...
给c++小白的教程10:一维数组
好久不见!我又来更教程了。 升到初二,由于学业原因,更新速度减慢了,十分抱歉! 以后将恢复到一周一次的频率 作者只是个普通学生,做的教程多有不足,希望大家批评指正! 赫炎今天在一…...

【排序】3.希尔排序法
希尔排序(直接插入排序的优化) 1.分组思想 上图中gap为5,说明要分成5组。 这5组分别用了五种颜色的线条连接起来了。 第1组:9、4 第2组:1、8 第3组:2、6 第4组:5、3 第5组:7、5 2.缩…...
商品详情数据API接口概述(json数据格式返回参考)
商品详情数据API接口是指一种编程接口(API,Application Programming Interface),它允许开发者或系统以编程方式获取商品的详细信息。这些信息包括但不限于SKU的详细信息、商品图片、商品属性、价格、库存状态、用户评价等。当调用…...

Jmeter简介
基础介绍 Jmeter录制脚本的原始是配置一个HTTP代理,然后浏览器通过这个代理访问测试页面从而完成脚本录制。 一、下载安装 jmeter本身不需要安装,需要配置环境变量JDK,然后打开bin文件夹中的jmeter.vbs即可。建议jdk 1.7及以上版本。 基本祖…...
网页前端开发之HTML入门篇:标题标签 heading
标题标签 heading <h1>-<h6>是HTML的标题标签,其标签内容会呈现六个不同级别的字号, <h1>字号最大,<h6>字号最小。 示例 <html><body><h1>一级标题</h1><h2>二级标题</h2>&l…...

医院信息化与智能化系统(3)
医院信息化与智能化系统(3) 这里只描述对应过程,和可能遇到的问题及解决办法以及对应的参考链接,并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图,可以试试PlantUML,告诉GPT你的文件结构,让他给你对应的…...
数据结构(线性表)
1线性表的定义与操作 1.1线性表的定义 线性表是一种基础的数据结构,其主要特点是:数据元素之间存在一种线性关系(一对一)。线性表的每一个数据元素都有一个唯一的前驱和后继,除了第一个元素没有前驱,最后…...
ArcGIS Pro SDK (十八)栅格
ArcGIS Pro SDK (十八)栅格 环境:Visual Studio 2022 + .NET6 + ArcGIS Pro SDK 3.0 栅格 1 在文件夹中打开栅格数据集 // 使用文件夹路径创建 FileSystemConnectionPath 对象。 FileSystemConnectionPath connectionPath = new FileSystemConnectionPath(new System...
c++ 对象作用域
在 C 中,对象的作用域(scope)指的是对象的生命周期以及对象在程序中可以访问的范围。作用域影响对象的创建、使用和销毁,主要有以下几种类型: 1. 局部作用域(Local Scope) 局部作用域的对象是…...
【无标题】海尔AI英语面试
1.自我介绍 Good morning. I am delighted to have this English interview. My name is fu guilin. I graduated from CDUT with a degree in Information engineering. During my university years, I have laid a solid foundation in my professional knowledge. I posses…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
C# SqlSugar:依赖注入与仓储模式实践
C# SqlSugar:依赖注入与仓储模式实践 在 C# 的应用开发中,数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护,许多开发者会选择成熟的 ORM(对象关系映射)框架,SqlSugar 就是其中备受…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...