101 - Lecture 11

news/2024/10/22 9:58:51/

课程概述

•	汇编语言中的输出(Output in inline assembly)
•	汇编语言中的输入(Input in inline assembly)
•	printf 函数的更多细节
•	scanf 函数的更多细节
•	程序流程控制(Controlling program flow)
•	跳转指令(Jumps)
•	无条件跳转(Unconditional jumps)
•	有条件跳转(Conditional jumps)

1. 汇编语言中的输出

Output in inline assembly
• 在C语言中声明变量后,汇编语言可以通过以下方式调用printf输出

声明字符串: char format[] = "Hello World\n";,用于存储需要输出的字符串。
lea eax, format   // 将字符串 'format' 的**地址**加载(load)到 eax 中
push eax          // 将字符串地址压入栈中(address of string, stack parameter)
call printf       // 调用 printf 库函数(use library code subroutine)
add esp, 4        // 清理栈上4字节的参数(clean 4 byte parameter off stack)

等效的C代码为:printf(“Hello World\n”);

输出数字的示例:

•	通过汇编调用printf输出整数:

声明格式字符串:声明格式化字符串 char format[] = “%d\n”;,用于指定printf以十进制的形式输出整数。
声明整数变量:声明一个整数变量 int myint = 157;,用于存储要输出的值。

push myint         // 将**变量的值**压入栈中
lea eax, format    // 将格式字符串的地址加载到 eax 中(address of the format string is saved in max)
push eax           // 将**格式字符串地址**压入栈中
call printf        // 调用 printf 函数(it will take two parameters from the stack)
add esp, 8         // 清理栈上两个参数的位置(clean up top two position in the stack)

在C语言中的等效代码为:printf(“%d”, myint);

Qualifier(限定词/修饰符) “%d” means the content of ‘myint’ will be printed as a decimal integer(十进制整数)

• scanf的作用是接收用户输入并存储在指定的变量中。因此,scanf不仅需要知道你希望存储数据的位置,还需要有权限去修改该变量的值。为了实现这一点,scanf需要获取变量的地址,从而能够直接修改变量的内容。
如果我们仅仅将变量的值压入栈中,scanf就无法知道应当在哪里存储输入的数据。因此,我们需要将变量的地址(而不是变量的值)压入栈中,以便scanf能够根据地址找到相应的内存位置来存储用户输入的值。

汇编语言中调用 printf 输出整数时的步骤。

  1. 压入第二个参数:Push the second parameter(integer variable to the stack)

    • 首先,将第二个参数(即要输出的整数值)压入栈中。因为 printf 需要先接收到数据才能进行输出,所以整数值作为输出的参数需要首先压入栈中。

  2. 压入第一个参数:push the first parameter(actually, address of the string)to the stack

    • 接着,将第一个参数压入栈中。在这里,第一个参数实际上是格式化字符串(如"%d"),它告诉 printf 应该如何处理输出的值。因此,压入的并不是格式字符串的内容,而是格式字符串的地址。

  3. 调用 printf 函数:call printf routine

    • 之后,调用 printf 函数。此时 printf 函数从栈中获取刚刚压入的两个参数:第一个是格式化字符串,第二个是要输出的整数。

  4. 清理栈:clean up top two positions in the stack

    • 最后,清理栈顶的两个位置。由于刚刚压入了两个参数,在调用 printf 之后,这两个参数仍然在栈中,所以需要将这两个参数从栈中移除,以确保栈处于干净状态,防止内存泄漏或混乱。

2. 汇编语言中的输入

Input in inline assembly
call to the standard C library routine: scanf(“%d”,&input);

• &input presents the address of the variable ‘input’

使用scanf读取用户输入并存储到变量中:

char format[] = "%d";//声明格式化字符串,用于指定 scanf 以十进制整数的格式读取用户输入。
int input;//声明一个整数变量 input,用于存储用户输入的数据。lea eax, input     // 将变量 input 的地址加载到 eax 中
push eax           // 将变量地址压入栈中
lea eax, format    // 将格式字符串的地址加载到 eax 中(adress of the format string is saved in eax)
push eax           // 将格式字符串地址压入栈中
call scanf         // 调用 scanf 函数
add esp, 8         // 清理栈上两个参数的位置(clean top two position in the stack)

_asm 是 inline assembly(内联汇编)的缩写,用于在 C 语言代码中插入汇编语言指令。
这里,input是用于存储用户输入的整数变量,format表示格式化字符串"%d",用于读取整数。

3. More about printf和scanf

printf的类型修饰符(qualifiers)
• %c:输出字符(character)
• %d或%i:输出有符号的十进制整数(a signed decimal number)
• %s:输出字符串(a string of characters)
scanf的类型修饰符(qualifiers)
• %c:读取一个字符(a single character)
• %d:读取一个有符号的十进制整数
• %s:读取一个字符串,直到遇到空格、换行或终止符(a string of characters until a white space or terminator(blank, new line, tab)is found)

4. 程序流程控制

Controlling program flow
very few programs execute all instructions sequentially,from the first till the last one.Usually,one needs to control the flow of the program.
• 很少有程序从头到尾按顺序执行所有指令,通常需要跳转或循环:
• 根据条件从一个位置跳转到另一个位置。
• 当某个条件(condition)满足或直到某个条件达到时重复操作(repeat some action)。
• 通过调用和返回控制程序流程。(Passing control to and from procedures)

Jumps

跳转指令分类:
“跳转”是改变程序控制流(program control)从一个位置到另一个位置的最直接(straightforward)的方法
无条件跳转:(Unconditional)
• JMP指令无条件地将控制转移到另一条指令。
• 语法:JMP <目标指令的地址>
Syntax:JMP<address of the target instruction>
•目标指令的位置可以通过它的标签(label)来指定

标签通常是一个符号名称,用来标识代码中的一个位置,使得在程序的其他地方可以通过引用这个标签来跳转到这个位置执行代码

有条件跳转:(Conditional)
• 先测试条件,再根据条件决定跳转与否。
• 常见指令包括JCXZ和JECXZ,它们测试寄存器CX或ECX是否为零,其他跳转指令测试状态标志(status flags)。

5. 条件跳转指令

Jumping based on status flags

• 条件跳转指令根据状态标志的设置跳转(Jumping based on status flags),包括:
• JC / JB:如果进位标志设置(=1),则跳转。carry flag is set
• JNC / JNB:如果进位标志未设置(=0),则跳转。carry flag is clear
• JE / JZ:如果零标志设置(=1),则跳转。zero flag is set
• JNE / JNZ:如果零标志未设置(=0),则跳转。zero flag is clear
• JS:如果符号标志设置(=1),则跳转。sign flag is set
• JNS:如果符号标志未设置(=0),则跳转。sign flag is clear
• JO: Overflow flag is set (=1)
• JNO: Overflow flag is clear (=0)

Jumps Based on Comparison of Two Values

基于比较的跳转:

•	CMP指令最常用来测试条件跳转。它比较两个值并根据比较结果修改状态标志,而不改变比较的值。
•	常见条件跳转:
•	JE:第一个操作数等于第二个操作数时跳转。
•	JNE:第一个操作数不等于第二个操作数时跳转。
•	JG:第一个操作数大于第二个操作数时跳转。
•	JL:第一个操作数小于第二个操作数时跳转。

当执行 cmp eax, ebx 时,CPU 会将 eax 和 ebx 中的值进行减法操作(不改变这两个寄存器的值,只是隐式地进行减法),并根据减法结果设置状态标志。
• 如果 eax 和 ebx 的值相等:
• 零标志(Z) 将被设置为1(Z = 1),表示比较结果为零。
• 如果 eax 和 ebx 的值不相等:
• 零标志(Z)将被清除(Z = 0),表示比较结果不为零。

Example:
cmp ax, bx        ; 比较 AX 和 BX 的值
jg  label1        ; 如果 AX > BX,跳转到 label1
jl  label2        ; 如果 AX < BX,跳转到 label2
add ax, input     ; 将 input 的值加到 AX
cmp ax, 0         ; 比较 AX 和 0
jge label1        ; 如果 AX >= 0,跳转到 label1
jl  label2        ; 如果 AX < 0,跳转到 label2
  1. 示例问题解答

    • Q1: 在汇编代码中给printf传递两个参数时,第一个参数应该先压入栈中。(True or False)
    • 解答:False。调用printf时,应该先压入第二个参数,然后是第一个参数。
    • Q2: 在汇编中调用printf时,传递给它的参数将被printf从栈中弹出。(True or False)
    • 解答:True。printf会从栈中弹出传递给它的参数。
    • Q3: 在汇编中调用scanf时,需要将接收输入的变量地址压入栈中。(True or False)
    • 解答:True。scanf需要接收变量的地址才能将输入数据存储在该变量中。
    • Q4: 在printf中打印字符串时,使用的转换说明符是什么?
    • 解答:%s。
    • Q5: 如果在调用scanf时有三个整数参数被压入栈中,返回时如何调整寄存器esp的值?
    • 解答:需要将esp增加12,因为每个整数占4字节,三个整数总共12字节。
    • Q6: 执行cmp eax, ebx时会检查零标志的设置。(True or False)
    • 解答:True。cmp指令会根据比较结果设置零标志,如果eax和ebx相等,则设置零标志为1。


http://www.ppmy.cn/news/1541032.html

相关文章

数据库作业2

作业&#xff1a; 建立数据库&#xff1a; 建表&#xff1a; 插入数据&#xff1a; 查询&#xff1a; &#xff08;1&#xff09;&#xff1a; &#xff08;2&#xff09;&#xff1a; &#xff08;3&#xff09;&#xff1a; &#xff08;4&#xff09;&#xff1a; &#xf…

训练自己的语音并生成音频fish.audio

Fish Speech 是一个致力于提供高质量、易用且功能强大的语音合成解决方案的开源项目。它融合了多项先进的语音合成技术&#xff0c;为研究者、开发者和普通用户提供了一个功能丰富的语音合成平台。 fish.audio开发团队是我们是公认的开源SVC / TTS 项目的开创者在GitHub上拥有超…

通过 Twitter Token 实现授权与操作

通过 Twitter Token 实现授权与操作 一、Twitter API 概览 1.1 Twitter API 简介 Twitter API 是 Twitter 公司提供的一种编程接口,它允许开发者访问 Twitter 的海量数据,包括用户信息、推文内容、关系网络等。通过这些接口,开发者可以创建应用程序,实现自动化的社交媒体…

PyCharm借助MobaXterm跳板机连接服务器

服务器信息&#xff1a; Step 1 MovaXterm→Session→SSH输入服务器信息 Step 2 MovaXterm→Session→SSH→Network setting→SSG gateway(jump host) 输入跳板机信息 键入密码即可 Step 3 MovaXterm→Tunneling→New SSH tunnel 依次输入&#xff1a;A本机端口&#xff0c…

离散制造和流程制造分别是什么?它们有什么区别?

为何有的企业生产过程看似一气呵成&#xff0c;而有的则是由多个环节组合而成&#xff1f;其实这就涉及到了制造业的两种常见生产模式。 流程制造离散制造 那么&#xff0c;在生产管理方面&#xff0c;离散制造和流程制造分别有什么特点、区别呢&#xff1f; 今天&#xff0…

Electron-(三)网页报错处理与请求监听

在前端开发中&#xff0c;Electron 是一个强大的框架&#xff0c;它允许我们使用 Web 技术构建跨平台的桌面应用程序。在开发过程中&#xff0c;及时处理网页报错和监听请求是非常重要的环节。本文将详细介绍 Electron 中网页报错的日志记录、webContents 的监听事件以及如何监…

Web3的核心概念:去中心化如何改变互联网

Web3&#xff0c;作为互联网的下一代技术架构&#xff0c;正在重新定义用户与数据、平台之间的关系。与以往的Web2.0时代相比&#xff0c;Web3的核心在于去中心化的理念&#xff0c;旨在通过区块链等技术实现更高的透明度、安全性和用户控制权。 1. 数据的掌控与隐私保护 在W…

持续科技创新 高德亮相2024中国测绘地理信息科技年会

图为博览会期间, 自然资源部党组成员、副部长刘国洪前往高德企业展台参观。 10月15日&#xff0c;2024中国测绘地理信息科学技术年会暨中国测绘地理信息技术装备博览会在郑州召开。作为国内领先的地图厂商&#xff0c;高德地图凭借高精度高动态导航地图技术应用受邀参会。 本…