本章思考题

1.请简述NZCV这4个条件标志位的作用。

2.下面两条ADD指令能否编译成功?

add x0, x1, #4096
add x0, x1, #1,LSL 1

3.下面的示例代码中,X0寄存器的值是多少?

mov x1, 0xffffffffffffffff
mov x2, #2
adc x0, x1, x2

4.下面的示例代码中,SUBS指令对PSTATE寄存器有什么影响?

mov x1, 0x3
mov x2, 0x1
subs x0, x1, x2

5.在下面的示例代码中,X0寄存器的值是多少?

mov x1, #3
mov x2, #1
sbc x0, x1, x2

6.检查数组array[0, index −1]是否越界,需要判断两个条件:一是输入值是否大于或等于index,二是输入值是否小于0。如下两条指令可实现数组边界检查的功能,其中X0寄存器的值为数组的边界index,X1寄存器的值为输入值input。请解释这两条指令为什么能实现数组越界检查。

subs xzr,x1,x0
b.hs OutOfInex

7.在下面的示例代码中,W2和W3的值是多少?

ldr w1, =0x8000008a
asr w2, w1, 1
lsr w3, w1, 1

8.如果想在汇编代码中使某些特定的位翻转,该如何操作?

9.设置某个寄存器A的Bit[7, 4]为0x5。下面是C语言的伪代码,用变量val来表示寄存器A的值2,请使用BFI指令来实现。

val &=~ (0xf << 4)
val |= ((u64)0x5 << 4)

10.下面的示例代码中,X0和X1寄存器的值分别是多少?

mov x2, #0x8a
ubfx x0, x2, #4, #4
sbfx x1, x2, #4, #4

11.下面是用C语言来读取pmcr_el0寄存器Bit[15:11]的值,请使用汇编代码来实现。

val = read_sysreg(pmcr_el0)
val = val >> 11;
val &= 0x1f;

本章主要介绍A64指令集中的算术运算和移位指令。

4.1 条件操作码

A64指令集沿用了A32指令集中的条件操作,在PSTATE寄存器中有4个条件标志位,即NZCV,如表4.1所示。

表4.1 条件标志位

条件标志位

描  述

N

负数标志(上一次运算结果为负值)

Z

零结果标志(上一次运算结果为零)

C

进位标志(上一次运算结果发生了无符号数溢出)

V

溢出标志(上一次运算结果发生了有符号数溢出)

常见的条件操作后缀如表4.2所示。

表4.2 常见的条件操作后缀

后  缀

含义(整数运算)

条件标志位

条 件 码

EQ

相等

Z=1

0b0000

NE

不相等

Z=0

0b0001

CS/HS

发生了无符号数溢出

C=1

0b0010

CC/LO

没有发生无符号数溢出

C=0

0b0011

MI

负数

N=1

0b0100

PL

正数或零

N=0

0b0101

VS

溢出

V=1

0b0110

VC

未溢出

V=0

0b0111

HI

无符号数大于

(C=1) && (Z=0)

0b1000

LS

无符号数小于或等于

(C=0) || (Z=1)

0b1001

GE

有符号数大于或等于

N == V

0b1010

LT

有符号数小于

N!=V

0b1011

GT

有符号数大于

(Z==0) && (N==V)

0b1100

LE

有符号数小于或等于

(Z==1) || (N!=V)

0b1101

AL

无条件执行

0b1110

NV

无条件执行

0b1111

4.2 加法与减法指令

下面介绍常见的与加法和减法相关的指令。

4.2.1 ADD指令

普通的加法指令有下面几种用法。

  • 使用立即数的加法。
  • 使用寄存器的加法。
  • 使用移位操作的加法。

1.使用立即数的加法指令

使用立即数的加法指令格式如下。

ADD <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}

它的作用是把Xn/SP寄存器的值再加上立即数imm,把结果写入Xd/SP寄存器里。指令编码如图4.1所示。

▲图4.1 使用立即数的加法指令的编码

  • Xd/SP:目标寄存器,它对应指令编码中的Rd字段。
  • Xn/SP:源寄存器,它对应指令编码中的Rn字段。
  • imm:立即数,它对应指令编码中的imm12字段。它是一个无符号的立即数,取值范围为0~4095。
  • shift:可选项,用来表示算术左移操作。它对应指令编码中的sh字段。当sh字段为0时,表示“LSL #0”。当sh字段为1时,表示“LSL #12”。

【例4-1】下面是正确的用法。

 add x0, x1, #1 //把x1寄存器的值加上立即数1,结果写入x0寄存器中add x0, x1, #1,LSL 12  //把立即数1算术左移12位,然后再加上x1寄存器的值,结果写入x0寄存器中

【例4-2】下面是错误的用法。

add x0, x1, #4096
add x0, x1, #1,LSL 1

汇编器会报如下错误,其中第一条语句中立即数超过了范围,第二条语句中左移的位数只能是0或者12。

test.S: Assembler messages:
test.S: Error: immediate out of range
test.S: Error: shift amount must be 0 or 12 at operand 3 -- 'add x0,x1,#1,LSL 1'

2.使用寄存器的加法指令

使用寄存器的加法指令格式如下。

ADD <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}

这条指令的作用是先把Rm寄存器做一些扩展,例如左移操作,然后再加上Xn/SP寄存器的值,把结果写入Xd/SP寄存器中。

指令编码如图4.2所示。

▲图4.2 使用寄存器的加法指令编码

  • Xd/SP:目标寄存器,它对应指令编码中的Rd字段。
  • Xn/SP:第一个源操作数,它对应指令编码中的Rn字段。
  • R:表示第二个源操作数是64位还是32位的通用寄存器,它对应指令编码中的option字段。当option字段等于X11寄存器的值时,使用64位通用寄存器,其他情况下使用32位通用寄存器。
  • m:通用寄存器编号,和R结合来描述第二个源操作数,可以表示X0~X30或者W0~W30通用寄存器,它对应指令编码中的Rm字段。
  • extend:可选项,用于对第二个源操作数进行扩展计算,它对应指令编码中的option字段。当option = 000时,表示UXTB操作。UXTB表示对8位的数据进行无符号扩展。当option = 001时,表示UXTH操作。UXTB表示对16位的数据进行无符号扩展。当option = 010时,表示UXTW操作。UXTW表示对32位的数据进行无符号扩展。当option = 011时,表示LSL|UXTX操作。LSL表示逻辑左移,UXTX表示对64位数据进行无符号扩展。当option = 100时,表示SXTB操作。SXTB表示对8位的数据进行有符号扩展。当option = 101时,表示SXTH操作。SXTH表示对16位的数据进行有符号扩展。当option = 110时,表示SXTW操作。SXTW表示对32位的数据进行有符号扩展。当option = 111时,表示SXTX操作。SXTX表示对64位的数据进行有符号扩展。
  • amount:当extend为LSL操作时,它的取值范围是0~4,它对应指令编码中的imm3字段。

【例4-3】使用寄存器的加法指令如下。

add x0, x1, x2 //x0 = x1 + x2
add x0, x1, x2, LSL 2 //x0 = x1 + x2 << 2

【例4-4】下面也是使用寄存器的加法指令。

1 mov x1, #1
2 mov x2, #0x108a
3 add x0, x1, x2, UXTB
4 add x0, x1, x2, SXTB

上面的示例代码中,第3行的运行结果为0x8B,因为UXTB对X2寄存器的低8位数据进行无符号扩展,结果为0x8A,然后再加上X1寄存器的值,最终结果为0x8B。

在第4行中,SXTB对X2寄存器的低8位数据进行有符号扩展,结果为0xFFFFFFFFFFFFFF8A,然后再加上X1寄存器的值,最终结果为0xFFFFFFFFFFFFFF8B。

3.使用移位操作的加法指令

使用移位操作的加法指令的格式如下。

ADD <Xd>, <Xn>, <Xm>{, <shift> #<amount>}

这条指令的作用是先把Xm寄存器做一些移位操作,然后再加上Xn寄存器的值,结果写入Xd寄存器中。

指令编码如图4.3所示。

▲图4.3 使用移位操作的加法指令的编码

  • Xd:目标寄存器,它对应指令编码中的Rd字段。
  • Xn:第一个源操作数,它对应指令编码中的Rn字段。
  • Xm:第二个源操作数,它对应指令编码中的Rm字段。
  • shift:移位操作,它对应指令编码中的shift字段。当shift = 00时,表示LSL操作。当shift = 01时,表示LSR操作。当shift = 10时,表示ASR操作。
  • amount:移位的数量,取值范围是0~63,它对应指令编码中的imm6字段。

【例4-5】如下代码用于实现移位操作加法。

add x0, x1, x2, LSL 3 //x0 = x1 + x2 << 3

【例4-6】下面的代码是错误的。

add x0, x1, x2, LSL 64

amount参数已经超过了取值范围,汇编器会报错,报错的信息如下。

test.S: Assembler messages:
test.S: Error: shift amount out of range 0 to 63 at operand 3 – 'add x0,x1,x1,LSL 64'

4.2.2 ADDS指令

ADDS指令是ADD指令的变种,唯一的区别是指令执行结果会影响PSTATE寄存器的NZCV标志位,例如当计算结果发生无符号数溢出时,C=1。

【例4-7】下面的代码使用了ADDS指令。

mov x1, 0xffffffffffffffffadds x0, x1, #2mrs x2, nzcv

X1的值(0xFFFFFFFFFFFFFFFF)加上立即数2一定会触发无符号数溢出,最终X0寄存器的值为1,同时还设置PSTATE寄存器的C标志位为1。我们可以通过读取NZCV寄存器来判断,最终X2寄存器的值为0x20000000,说明第29位的C字段置1,如图4.4所示。

▲图4.4 NZCV寄存器

4.2.3 ADC指令

ADC是进位的加法指令,最终的计算结果需要考虑PSTATE寄存器的C标志位。ADC指令的格式如下。

ADC <Xd>, <Xn>, <Xm>

Xd寄存器的值等于Xn寄存器的值加上Xm寄存器的值加上C,其中C表示PSTATE寄存器的C标志位。

指令编码如图4.5所示。

▲图4.5 ADC指令的编码

  • Xd:目标寄存器,它对应指令编码中的Rd字段。
  • Xn:第一个源操作数,它对应指令编码中的Rn字段。
  • Xm:第二个源操作数,它对应指令编码中的Rm字段。

【例4-8】如下代码使用了ADC指令。

mov x1, 0xffffffffffffffff
mov x2, #2adc x0, x1, x2mrs x3, nzcv

ADC指令的计算过程是0xFFFFFFFFFFFFFFFF + 2 + C,因为0xFFFFFFFFFFFFFFFF + 2的过程中已经触发了无符号数溢出,C=1,所以最终计算X0寄存器的值为2。若读取NZCV寄存器,我们发现C标志位也被置位了。

4.2.4 SUB指令

普通的减法指令与加法指令类似,也有下面几种用法。

  • 使用立即数的减法。
  • 使用寄存器的减法。
  • 使用移位操作的减法。

1.使用立即数的减法指令

使用立即数的减法指令格式如下。

SUB <Xd|SP>, <Xn|SP>, #<imm>{, <shift>}

它的作用是把Xn/SP寄存器的值减去立即数imm,结果写入Xd/SP寄存器里。指令编码如图4.6所示。

▲图4.6 使用立即数的减法指令的编码

  • Xd/SP:目标寄存器,它对应指令编码中的Rd字段。
  • Xn/SP:源寄存器,它对应指令编码中的Rn字段。
  • imm:立即数,它对应指令编码中的imm12字段。它是一个无符号的立即数,取值范围为0~4095。
  • shift:可选项,用来表示算术左移操作。它对应指令编码中的sh字段。当sh字段为0时,表示“LSL #0”。当sh字段为1时,表示“LSL #12”。

【例4-9】如下代码使用了SUB指令。

sub x0, x1, #1 //把x1寄存器的值减去立即数1,结果写入x0寄存器
sub x0, x1, #1,LSL 12  //把立即数1算术左移12位,然后把x1寄存器中的值减去立即数1的结果算术左移//12位的值写入x0寄存器中

【例4-10】下面的用法是错误的。

sub x0, x1, #4097
sub x0, x1, #1,LSL 1

汇编器会报如下错误,其中第一条语句中立即数超过了范围,第二条语句中左移的位数只能是0或者12。

test.S: Assembler messages:
test.S: Error: immediate out of range
test.S: Error: unexpected characters following instruction at operand 3 -- 'sub x0,x1,#1,LSL 1'

2.使用寄存器的减法指令

使用寄存器的减法指令格式如下。

SUB <Xd|SP>, <Xn|SP>, <R><m>{, <extend> {#<amount>}}

这条指令的作用是先对Rm寄存器做一些扩展,例如左移操作,然后Xn/SP寄存器的值减Rm寄存器的值,把结果写入Xd/SP寄存器中。

指令编码如图4.7所示。

▲图4.7 使用寄存器的减法指令的编码

  • Xd/SP:目标寄存器,它对应指令编码中的Rd字段。
  • Xn/SP:第一个源操作数,它对应指令编码中的Rn字段。
  • R:表示第二个源操作数是64位还是32位的通用寄存器,它对应指令编码中的option字段。当option字段等于二进制位x11时,使用64位通用寄存器,其他情况下使用32位通用寄存器。
  • m:通用寄存器编号,和R结合来描述第二个源操作数,可以表示X0~X30或者W0~W30通用寄存器,它对应指令编码中的Rm字段。
  • extend:可选项,用于对第二个源操作数进行扩展计算,它对应指令编码中的option字段。当option=000时,表示UXTB操作。UXTB表示对8位的数据进行无符号扩展。当option = 001时,表示UXTH操作。UXTB表示对16位的数据进行无符号扩展。当option = 010时,表示UXTW操作。UXTW表示对32位的数据进行无符号扩展。当option = 011时,表示LSL|UXTX操作。LSL表示逻辑左移,UXTX表示对64位数据进行无符号扩展。当option = 100时,表示SXTB操作。SXTB表示对8位的数据进行有符号扩展。当option = 101时,表示SXTH操作。SXTH表示对16位的数据进行有符号扩展。当option = 110时,表示SXTW操作。SXTW表示对32位的数据进行有符号扩展。当option = 111时,表示SXTX操作。SXTX表示对64位的数据进行有符号扩展。
  • amount:当extend为LSL操作时,它的取值范围是0~4,它对应指令编码中的imm3字段。

【例4-11】如下代码使用了寄存器的减法指令。

sub x0, x1, x2 //x0 = x1 - x2
sub x0, x1, x2, LSL 2 //x0 = x1 - x2 << 2

【例4-12】下面的代码也使用了寄存器的减法指令。

1    mov x1, #1
2    mov x2, #0x108a
3    sub x0, x1, x2, UXTB
4    sub x0, x1, x2, SXTB

上面的示例代码中,UXTB对X2寄存器的低8位数据进行无符号扩展,结果为0x8A,然后再计算1 − 0x8A的值,最终结果为0xFFFFFFFFFFFFFF77。

在第4行中,SXTB对X2寄存器的低8位数据进行有符号扩展,结果为0xFFFFFFFFFFFFFF8A,然后再计算1 − 0xFFFFFFFFFFFFFF8A,最终结果为0x77。

3.使用移位操作的减法指令

使用移位操作的减法指令的格式如下。

SUB <Xd>, <Xn>, <Xm>{, <shift> #<amount>}

这条指令的作用是先把Xm寄存器做一些移位操作,然后使Xn寄存器中的值减去Xm寄存器中的值,把结果写入Xd寄存器中。

指令编码如图4.8所示。

▲图4.8 使用移位操作的减法指令的编码

  • Xd:目标寄存器,它对应指令编码中的Rd字段。
  • Xn:第一个源操作数,它对应指令编码中的Rn字段。
  • Xm:第二个源操作数,它对应指令编码中的Rm字段。
  • shift:移位操作,它对应指令编码中的shift字段。当shift = 00时,表示LSL操作。当shift=01时,表示LSR操作。当shift=10时,表示ASR操作。
  • amount:移位的数量,取值范围是0~63,它对应指令编码中的imm6字段。

【例4-13】下面的代码用于实现移位操作减法。

add x0, x1, x2, LSL 3 //x0 = x1 - x2 << 3

【例4-14】下面的代码是错误的。

sub x0, x1, x2, LSL 64

上述示例代码中的amount参数超过了取值范围,汇编器会报错,报错的信息如下。

test.S: Assembler messages:
test.S: Error: shift amount out of range 0 to 63 at operand 3 -- 'sub x0,x1,x1,LSL 64'

4.2.5 SUBS指令

SUBS指令是SUB指令的变种,唯一的区别是指令执行结果会影响PSTATE寄存器的NZCV标志位。SUBS指令判断是否影响NZCV标志位的方法比较特别,对应的伪代码如下。

operand2 = NOT(imm);
(result, nzcv) = AddWithCarry(operand1, operand2, '1');
PSTATE.<N,Z,C,V> = nzcv;

首先,把第二个操作数做取反操作。然后,根据式(4-1)计算。

  operand1 + NOT(operand2) + 1  (4-1)

NOT(operand2)表示把operand2按位取反。在这个计算过程中要考虑是否影响NZCV标志位。当计算结果发生无符号数溢出时,C=1;当计算结果为负数时,N=1。

【例4-15】如下代码会导致C标志位为1。

mov x1, 0x3
mov x2, 0x1subs x0, x1, x2mrs x3, nzcv

SUBS指令仅仅执行“3 − 1”的操作,为什么会发生无符号溢出呢?

第二个操作数为X2寄存器的值,对应值为1,按位取反之后为0xFFFFFFFFFFFFFFFE。根据计算公式,计算3 + 0xFFFFFFFFFFFFFFFE + 1,这个过程会发生无符号数溢出,因此4个标志位中的C=1,最终计算结果为2。因此,最后一行读取NZCV寄存器的值——0x20000000。

【例4-16】如下代码会导致CZ标志位都置1。

mov x1, 0x3
mov x2, 0x3subs x0, x1, x2mrs x3, nzcv

第二个操作数为X2寄存器的值,该值为3,按位取反之后为0xFFFFFFFFFFFFFFFC。根据公式计算3 + 0xFFFFFFFFFFFFFFFC + 1的过程中会发生无符号数溢出,因此C=1。另外,最终结果为0,所以Z=1。

4.2.6 SBC指令

SBC是进位的减法指令,也就是最终的计算结果需要考虑PSTATE寄存器的C标志位。SBC指令的格式如下。

SBC <Xd>, <Xn>, <Xm>

下面是SBC指令中对应的伪代码。

operand2 = NOT(operand2);
(result, -) = AddWithCarry(operand1, operand2, PSTATE.C);
X[d] = result;

所以,SBC指令的计算过程是,首先对第二个操作数做取反操作,然后把第一个操作数、第二个操作数相加,这个过程会影响PSTATE寄存器的C标志位,最后把C标志位加上。

综上所述,SBC指令的计算公式为

Xd = Xn + NOT(Xm) + C  (4-2)

指令编码如图4.9所示。

https://www.epubit.com/center?id=BF106D63-C122-4A3E-9B6A-CC182DFB9F41

▲图4.9 SBC指令的编码

  • Xd:目标寄存器,它对应指令编码中的Rd字段。
  • Xn:第一个源操作数,它对应指令编码中的Rn字段。
  • Xm:第二个源操作数,它对应指令编码中的Rm字段。

【例4-17】如下代码使用了SBC指令。

mov x1, #3
mov x2, #1sbc x0, x1, x2mrs x3, nzcv

SBC指令的计算过程是3 + NOT(1) + C。NOT(1)表示对立即数1按位取反,结果为0xFFFFFFFFFFFFFFFE。那么,计算3 + 0xFFFFFFFFFFFFFFFE的过程中会发生无符号数溢出,C=1,再加上C标志位,最后计算结果为2。

4.3 CMP指令

CMP指令用来比较两个数的大小。在A64指令集的实现中,CMP指令内部调用SUBS指令来实现。

1.使用立即数的CMP指令

使用立即数的CMP指令的格式如下。

CMP <Xn|SP>, #<imm>{, <shift>}

上述指令等同于如下指令。

SUBS XZR, <Xn|SP>, #<imm> {, <shift>}

2.使用寄存器的CMP指令

使用寄存器的CMP指令的格式如下。

CMP <Xn|SP>, <R><m>{, <extend> {#<amount>}}

上述指令等同于如下指令。

SUBS XZR, <Xn|SP>, <R><m>{, <extend> {#<amount>}}

3.使用移位操作的CMP指令

使用移位操作的CMP指令的格式如下。

CMP <Xn>, <Xm>{, <shift> #<amount>}

上述指令等同于如下指令。

SUBS XZR, <Xn>, <Xm> {, <shift> #<amount>}

4.CMP指令与条件操作后缀

CMP指令常常和跳转指令与条件操作后缀搭配使用,例如条件操作后缀CS表示是否发生了无符号数溢出,即C标志位是否置位,CC表示C标志位没有置位。

【例4-18】使用CMP指令来比较如下两个寄存器。

cmp x1, x2
b.cs  label

CMP指令判断两个寄存器是否触发无符号溢出的计算公式与SUBS指令类似:

X1 + NOT(X2) + 1  (4-3)

如果上述过程中发生了无符号数溢出,那么C标志位会置1,则b.cs指令将会跳转到label处。

【例4-19】下面的代码用来比较3和2两个立即数。

my_test:mov x1, #3mov x2, #2
1:cmp x1, x2b.cs 1bret

至于如何比较,需要根据b指令后面的条件操作后缀来定。CS表示判断是否发生无符号数溢出。根据式(4-3)可得,3 + NOT(2) +1,其中NOT(2)把立即数2按位取反,取反后为0xFFFFFFFFFFFFFFFD。3 + 0xFFFFFFFFFFFFFFFD + 1的最终结果为1,这个过程中发生了无符号数溢出,C标志位为1。所以,b.cs的判断条件成立,跳转到标签1处,继续执行。

【例4-20】下面的代码比较X1和X2寄存器的值大小。

my_test:mov x1, #3mov x2, #2
1:cmp x1, x2b.ls 1bret

在比较X1和X2寄存器的值大小时,判断条件为LS,表示无符号数小于或者等于。那么,这个比较过程中,我们就不需要判断C标志位了,直接判断X1寄存器的值是否小于或者等于X2寄存器的值即可,因此这里b指令不会跳转到标签1处。

本文截选自《ARM64体系结构编程与实践》第4章:A64指令集2——算术与移位指令

本书旨在详细介绍ARM64体系结构的相关技术。本书首先介绍了ARM64体系结构的基础知识、搭建树莓派实验环境的方法,然后讲述了ARM64指令集中的加载与存储指令、算术与移位指令、比较与跳转等指令以及ARM64指令集中的陷阱,接着讨论了GNU汇编器、链接器、链接脚本、GCC内嵌汇编代码、异常处理、中断处理、GIC-V2,最后剖析了内存管理、高速缓存、缓存一致性、TLB管理、内存屏障指令、原子操作、操作系统等内容。
本书适合嵌入式开发人员阅读。

ARM64体系结构编程与实践:算术与移位指令相关推荐

  1. python录入学生信息网_干货满满 | Python趣味编程教学实践

    Python趣味编程教学实践 近几年间,Python 的火热有目共睹,在IEEE Spectrum 2020 编程语言 Top 10排行榜中,Python位居第一.这是因为Python 与人工智能.机 ...

  2. Linux内存管理:ARM64体系结构与编程之cache(3):cache一致性协议(MESI、MOESI)、cache伪共享

    目录 为什么系统软件人员要深入了解cache? cache一致性协议 神马是MESI协议? MESI的操作 MESI状态图 演示:初始化状态为I的cache line 当本地CPU的缓存行状态为I时, ...

  3. Linux内存管理:ARM64体系结构与编程之cache(2):cache一致性

    <Linux内存管理:ARM64体系结构与编程之cache(1)> <Linux内存管理:ARM64体系结构与编程之cache(2)> <ARM SMMU原理与IOMMU ...

  4. Linux内存管理:ARM64体系结构与编程之cache(1)

    <Linux内存管理:ARM64体系结构与编程之cache(1)> <Linux内存管理:ARM64体系结构与编程之cache(2)> <ARM SMMU原理与IOMMU ...

  5. 1.3编程基础之算术表达式与顺序执行(20题)-2022.02.26

    1.3编程基础之算术表达式与顺序执行 01 A+B问题 (Python3实现) 1.3编程基础之算术表达式与顺序执行 01 A+B问题 (Python3实现)_青少年趣味编程-CSDN博客 P1001 ...

  6. 1.3 编程基础之算术表达式与顺序执行(20题)

    1.3编程基础之算术表达式与顺序执行 01 A+B问题 (Python3实现) https://blog.csdn.net/dllglvzhenfeng/article/details/1226799 ...

  7. 1.3编程基础之算术表达式与顺序执行 01 A+B问题 (Python3实现)

    http://noi.openjudge.cn/ch0103/01/ https://www.luogu.com.cn/problem/P1001 """ P1001 A ...

  8. 1.3编程基础之算术表达式与顺序执行 01 A+B问题

    http://noi.openjudge.cn/ch0103/01/ #include <bits/stdc++.h> using namespace std; int main() {i ...

  9. 1.3编程基础之算术表达式与顺序执行 02 计算(a+b)*c的值

    http://noi.openjudge.cn/ch0103/02/ #include <iostream> #include <bits/stdc++.h> using na ...

  10. 1.3编程基础之算术表达式与顺序执行 03 计算(a+b) c的值

    http://noi.openjudge.cn/ch0103/01/ #include <bits/stdc++.h> using namespace std; int main() {i ...

最新文章

  1. noip提高组2000 乘积最大
  2. 华为服务器提示错误信息,服务器错误日志
  3. spring depends-on 不起作用
  4. LeetCode 623. 在二叉树中增加一行(BFS/DFS)
  5. php的web表单系统源码毕设_从业十多年看了千百套Java毕设项目,整理出100个精品!免费分享...
  6. shell逐行读取文件拼接Sql语句并访问数据库
  7. Oracle In子句
  8. 苹果mac专业音频处理软件:Audition
  9. 如何动/静 态 两种方式修改Static控件的颜色
  10. Hive安装详细步骤
  11. C51单片机实验——定时器实验
  12. 【JavaWeb】button自带的reset方法
  13. 7-27 冒泡法排序 (20分)
  14. 2021年10月考试总结
  15. 小写数字转成大写的中文,方便财务对账专用
  16. 单调栈和单调队列的本质区别
  17. NET CORE Learning
  18. Java中使用HSSFWorkbook POI导出下载excel文件
  19. C语言fgets()函数
  20. 用R语言画切线和法线

热门文章

  1. (组合数 +快速幂+逆元+费马小引理)acwing 886. 求组合数 II
  2. 深度神经网络分析,神经网络 炒股
  3. 先有鸡还是先有鸡蛋?C语言发展史给出的答案
  4. 将1自动补位为01_英雄联盟如何避免被自动补位到辅助位置
  5. VTK:二次六面体用法实战
  6. MongoDB中balancer操作
  7. 【机器学习】(十)核支持向量机SVM:make_blobs方法,hstack() 函数
  8. java 163邮箱发邮件_java用163邮箱发邮件的方式,步骤有哪些?
  9. 微信web中IOS系统手机摇一摇功能实现及问题解决
  10. python转xlsx为xls 或重新保存xls