乱码三千 – 分享实用IT技术

乱码三千 – 码出一个新世界


  • 首页

  • 归档

  • 搜索

GCC工具链都包含哪些工具

发表于 2021-01-27

GCC

GCC原名为GNU C语言编译器(GNU C Compiler),原本只能处理C语言。后来随着功能的扩展,支持的语言种类越来越多 ,故更名为GCC(GNU Compiler Collection,GNU编译器套件)

因此 GCC既可以指代C编译器,也可以指代GNU编译套件

其套件囊括了许多子工具:

  • gcc: C 编译器

  • g++: C++ 编译器

  • cpp: C 预处理器

  • as: 汇编器

  • ld: 连接器

  • objcopy: 目标文件翻译器,用于从连接器输出中创建一个ROM 映像

  • objdump: 目标文件阅读器, 用于反汇编目标文件

  • make: make 工具

  • gdb: 源代码调试器

GCC工具链

一个程序从代码编译到机器执行,中间需要经历很多步骤,比如从预编译,编译,到汇编和连接, 这一系列环环相扣过程中涉及到的GNU工具集,称之为GCC工具链

在windows平台中,我们有许多的图形化IDE可以选择,一般编译工具链都集成进了软件内部,无需开发者关心,但是在Linux平台,基本以命令行的方式进行操作,那么对于开发者来说,需要了解每个工具的作用和具体使用方法

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

汇编语言之GNU ARM

发表于 2021-01-25

什么是GNU

GNU最开始其实是一个操作系统,旨为打造一个开源免费自由的操作系统,目前操作系统还在完善中

GNU计划: 最初目标是创建一套完全自由的操作系统GNU 和相应的软件

GCC :(GNU Compiler Collection)GNU编译器套件,GNU提供的一整套的工具集,这套工具集中包含了汇编器,编译器和链接器,二进制转换,调试工具等

GCC优势:

  • 免费开源
  • 贴近系统底层,功能强大,灵活性高
  • 跨平台,方便交叉编译

GCC劣势:

  • 工具基本采用命令行方式,学习和使用门槛较高

接下来我们要学习的就是GNU计划众多的产物之一GNU FOR ARM

汇编器与指令集

  1. 什么是汇编器

    将汇编语言翻译成机器码的工具

  2. 什么是编译器

    将高级语言翻译成机器语言或者汇编语言的工具

  3. 汇编器和编译器的区别

    汇编器的服务对象是汇编语言,编译器的服务对象是高级语言

  4. 汇编器和汇编语法伪指令的关系

    不同的CPU对应不同的指令集 ,不同的汇编器对应不同的伪指令集和汇编语法。

    每种汇编器都可以有自己的伪指令集和自己的语法

使用不同的汇编器汇编同一个cpu架构的汇编代码,所对应的指令绝对是一致的,但伪指令各有千秋

1
2
3
4
5
6
7
8
9
;使用ARM官方的汇编器
AREA test, CODE
mov R3,#5
END

;使用GNU的汇编器
.text ;伪指令
mov R3,#5 ;传送指令皆为mov
.end

常见的汇编器

  • MASM汇编器:微软旗下专为x86架构打造的一款汇编器,支持8086汇编和win32汇编
  • GNU汇编器 : 简称为GAS,是GNU旗下的一款免费开源跨平台汇编器其子集中包含了支持多种架构的汇编器,比如GNU FOR ARM就是单独面向ARM架构的汇编器,此外还有GNU FOR X86等
  • NASM汇编器: 是一款面向x86架构的汇编器,支持8086汇编和win32汇编,同时可跨平台, 免费开源
  • ARMASM汇编器:ARM官方原生的汇编器,集成在了ADS工具上,适用于ARM架构,我们也一般称之为ADS汇编器

两种ARM汇编器的各自用途

  • ARMASM汇编器:一般用于windows平台
  • GAS汇编器:支持windows平台和linux平台,方便跨平台交叉编译

由于移动设备如安卓和iphone底层都是采用GNU的编译环境,我们如果要进行移动端的开发,那么势必需要掌握GNU ARM, 同时和ADS和KEIL收费工具相比,GUN工具全部免费,方便开发者进行使用

如果你是从事android开发,有兴趣可以去翻NDK r17以下版本的库,里面用的编译工具就是GCC

GNU ARM开发环境搭建

我们需要准备以下两个工具:

  1. GCC编译套件
  2. 安卓模拟器

GCC编译套件根据cpu架构和操作系统的不同,又分为了很多子类:

  • 纯ARM裸机: 对应arm-none-eabi工具包
  • ARM架构+Linux操作系统:对应arm-none-linux-eabi工具包

由于接下来我们选择在安卓模拟器上进行开发学习,因此我们选择arm-none-linux-eabi这套工具来进行代码的编译

工具下载

GCC工具的具体使用

伪指令和伪操作

  1. 注释

    1
    @我是注释
  2. 段的声明

    • 代码段

      1
      2
      .text
      @代码
    • 数据段

      1
      2
      .data
      @代码
  • 自定义一个段

    1
    .section .pangshu @定义一个名为.panghsu的段
  1. 函数或者标签的声明

    1
    2
    3
    fun:  @在GNU环境中标签后面需要加冒号,而原生环境则不用
    mov R0,#4
    bx lr
  2. 数据的声明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    .byte @定义单字节数据,例如:.byte 0x14;
    .short @定义双字节数据,例如:.short 0x1000;
    .long @定义四字节数据,例如:.long 0x10001000;
    .quad @定义8字节,如:.quad 0x1234567890abcd;
    .float @定义浮点数,如:.float 0f-314159265358979323846264338327/95028841971.693993751E-40 @ -pi

    @字符串定义
    .string “abcd”, “efgh”, “hello!”
    .asciz “qwer”, “sun”, “world!”
    .ascii “welcome/0”
    @需要注意的是:.ascii伪操作定义的字符串需要自行添加结尾字符’/0’。
  3. 数据的批量定义

    • 格式如下:

      1
      2
      3
      .rept @重复次数
      @数据定义代码
      .endr @结束重复定义
    • 示例

      1
      2
      3
      .rept 3
      .byte 0x23
      .endr
  4. 关于align

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    .global _start
    _start:
    mov r0, #0x12

    .byte 0x12
    .byte 0x34

    ;.align 后跟为0,1,2或者不跟参数时都当作是4字节对齐
    .align
    .byte 0x56

    ; 2^3次方,8字节对齐
    .align 3
    .word 0x1

    ; 2^5次访,32字节对齐
    .align 5
    .word 0x2

    ; 填充0x12345678,直到16字节对齐
    .balignl 16,0x12345678

    ;字符串
    .ascii "abc123"

    .align
    ;.ascii和.asciz的区别是,.asciz会在字符串后自动添加结束符\0.
    .asciz "def456"

    mov r0, #0xab

    ;.balign[wl] align, fill_value, max_padding
    .align
    ; .balign 后跟的align参数必须为2的次方,否则会报错,按字节填充, fill_value要为字节
    .balign 8, 0x12

    ; .balignw 按2字节填充
    .balignw 8, 0x3456

    ; .balignl 按4字节填充
    .balignl 8, 0xabcdef01

    反汇编后的结果:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    00000000 <_start>:
    0: e3a00012 mov r0, #18
    4: 3412 .short 0x3412 // .byte 0x12 和 .byte 0x34
    6: 0000 .short 0x0000 // .align 引起的填充
    8: 00000056 andeq r0, r0, r6, asr r0 // .byte 0x56
    c: e1a00000 nop ; (mov r0, r0) // .align 3 8字节对齐
    10: 00000001 .word 0x00000001 // .word 0x1
    14: e1a00000 nop ; (mov r0, r0) // .align 5 ,32字节对齐
    18: e1a00000 nop ; (mov r0, r0)
    1c: e1a00000 nop ; (mov r0, r0)
    20: 00000002 .word 0x00000002 // .word 0x2
    24: 12345678 .word 0x12345678 // .balignl 16,0x12345678,填充0x12345678,直到16字节对齐
    28: 12345678 .word 0x12345678
    2c: 12345678 .word 0x12345678
    30: 31636261 .word 0x31636261 // .ascii "abc123"
    34: 3332 .short 0x3332
    36: 0000 .short 0x0000
    38: 34666564 .word 0x34666564 // .asciz "def456"
    3c: 3635 .short 0x3635
    3e: 00 .byte 0x00
    3f: e3a000ab mov r0, #171 ; 0xab // mov r0, #0xab, 这里就不对齐了
    43: 00 .byte 0x00
    44: 12121212 .word 0x12121212 // .balign 8, 0x12
    48: e1a00000 nop ; (mov r0, r0)
    4c: e1a00000 nop ; (mov r0, r0)
    50: e1a00000 nop ; (mov r0, r0)
    54: e1a00000 nop ; (mov r0, r0)
    58: e1a00000 nop ; (mov r0, r0)
    5c: e1a00000 nop ; (mov r0, r0)

指令和伪指令的区别

  • 指令: 有与之对应的机器码,能被cpu所识别,和编译器无关

  • 伪指令:没有与之对应的机器码,无法被cpu识别,只能被编译器识别,不同编译器伪指令不一样

    不同的CPU对应不同的指令集;不同的汇编器对应不同的语法和伪指令集

例子:ARM原生编译器和GNU FOR ARM

两种汇编器语法对比一览表

GNU ARM汇编 ADS ARM汇编
“@”或“/…/” “;”
.include GET
.equ EQU
.global EXPORT
.extern IMPORT
.long DCD
.end END
entry: ENTRY
.text AREA Init,CODE,READONLY
.data AREA Block,DATA,READWRITE
.macro MACRO
.endm MEND

汇编语言和C语言交互

1.引入其他源文件函数

使用import或者extern伪指令

1
2
3
4
5
6
7
8
9
;使用import伪指令
AREA code, CODE
import fun1 ;导入其他源文件中名为fun1的函数
END

;使用extern伪指令
AREA code, CODE
extern fun1
END

两者区别:

  • import:不管当前文件是否使用该引入的函数,该标签都会加入当前文件符号表,即为静态引用
  • extern:只有当前文件使用了该函数,才会将此标签加入符号表,即为动态引用

2.导出当前源文件中函数供其他文件访问

使用export或者global伪指令

1
2
3
4
5
6
7
8
;使用import伪指令
AREA code, CODE
export fun ;导出fun函数供其他源文件使用

fun
mov R0,#4
bx lr
END

3.外链汇编之C语言调汇编函数

第一步,在汇编原文件中将函数暴露出来给供外部调用,使用export或者global伪指令:

1
2
3
4
5
6
7
8
9
10
11
12
AREA code, CODE
export arm_strcpy ;或者使用global

arm_strcpy
loop
ldrb R4,[R0],#1 ;如果使用ldr 那么将偏移值改成4
cmp R4,#0
beq over
strb R4,[R1],#1
b loop
over
END

第二步,在C文件中引用汇编中的函数,C文件中只能使用extern伪指令:

1
2
3
4
5
6
7
extern arm_strcpy(char *src,char*des);

int main2(){
char *a="hello pangshu";
char b[64];
arm_strcpy(a,b);
}

4.外链汇编之汇编调c语言函数

第一步,在C文件中编写好函数

1
2
3
int c_sum(int a,int b){
return a+b;
}

第二步, 在汇编文件中引入函数,使用import或者extern伪指令

1
2
3
4
5
6
7
AREA code, CODE
import c_sum

mov R0,#1 ;第一个参数
mov R1,#2 ;第二个参数

END

第三步, 使用BL指令调用函数

1
2
3
4
5
6
7
AREA code, CODE
import c_sum

mov R0,#1 ;第一个参数
mov R1,#2 ;第二个参数
BL c_sum
END

在ARM中函数参数使用R0~R3这三个寄存器来进行传递,最多传递4个参数,超过4个参数使用栈进行处理,函数返回值通过R0进行传递

5.内嵌汇编

GNU内嵌汇编,格式如下:

1
2
3
4
5
6
7
int main2(){
__asm__( //大括号改成中括号
"mov R5,#0x00000005\n" //汇编指令需要使用引号包裹,多条语句之间使用回车换行符进行分隔
"mov R6,#0x00000005"
); //需要以分号结尾
return 0;
}

学习工具

  • 在线ARM汇编编辑器:https://azm.azerialabs.com/

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

视频帧率和码率对视频质量和文件大小的影响

发表于 2021-01-24

我们从画面流畅度,画面清晰度,和视频文件体积三个方面进行分析:

帧率(FPS)

指每秒显示图像的张数

比如30帧,表示每秒显示30张图像

帧率越大,画面越流畅,帧率越小,画面越卡顿,如果低到1帧/秒,那么就相当于一个幻灯片了

帧率不会影响到画面的清晰度,只会影响画面的流畅度和文件的体积,帧率越大,视频对应的体积越大

分辨率(resolution)

指像素点分布密度

比如24寸的显示器,设置1920x1080的分辨率,那就是横向由1920个像素点构成,纵向由1080个像素点构成,也就是说在屏幕尺寸固定的情况下,分辨率越高,画面越清晰细腻,反之,画面越模糊

分辨率不会影响画面的流畅度,只会影响画面的清晰度和文件的体积,分辨率越大,视频体积越大

码率(Bitrate)

指每秒传输的数据位数,单位kbps 即千位每秒 ,这里的位指的是二进制位

基本的算法是:

  • 每秒传输的数据量=码率/8

  • 视频文件体积=码率/8x视频时长(s) =每秒传输的数据量*视频时长(s)

比如500Kbps,也就是每秒传输62K大小的数据, 假如按照帧率30fps进行计算,那么每张图片大小约为2kb大小

也就是说视频时长固定的情况下,码率越高,文件体积越大,同时视频显示的有效像素越多,视频更加接近原始分辨率,反之,码率越低,文件体积越小,但是视频能显示的有效像素就越少,原本1080p的分辨率,每帧图像至少需要占用20k的数据量,但是码率过低每帧只能分配2K的量,此时像素点显示不全,就会造成视频模糊不清晰

因此,码率若是过低,再高的分辨率都拯救不了画质,反而会适得其反,

事实上,低码率环境下,低分辨率画面要比高分辨率画面更加清晰

码率不会影响画面的流畅度,但是会影响画面的清晰度和文件的体积

我们的需求

我们一般追求高清流畅的画质,同时文件体积尽可能小,那么该如何找到帧率 码率和分辨率三者的平衡点呢?

首先在我们录制视频的时候,屏幕的分辨率一般是固定的,随着不同的电脑分辨率也不同(当然你要手动调整也行)

其次,为了保证视频的流畅度我们一般将帧率设置在25fps以上

那么我们想减小视频的体积的话,只能从码率入手了, 找到一个画质能接受,体积小的平衡点

比如1980x1080的分辨率,我使用500kbps左右的码率,差不多可以接受,OBS在录制时默认也是在这个码率内来回波动

以下是常见分辨率和码率之间平衡参考表:

举例:如果要想百分百还原1080p HQ的画质,至少需要5.76Mkpbs码率的支撑,如果是直播的话需要至少9M的宽带才能稳定传输对应的数据量,否则画面卡顿

直播中,在分辨率和网速一定的情况下,我们会适当降低码率,牺牲部分清晰度的来保证视频的流畅性

如果网速不行又希望画面还清晰流畅,那么就降低拍摄的分辨率,同时降低数据传输量也就是码率值,当然分辨率降低之后所谓的视频清晰度也只是相对的,凡事总有取舍

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

关于mysql崩溃之error establishing a database connection

发表于 2021-01-22

起因

最近在进行网站检查的时候突然发现我的一个子网站挂了,提示error establishing a database connection, 如果是网站刚建立那好解决,80%的概率是数据连接参数不正确,或者是数据库端口没有开放

但是我这个网站运行很长一段时间了,之前一直好好的,突然之间就挂了, 而且这个数据库我使用的是docker进行维护,同时,在同一个mysql容器中我放置了好几个网站的数据,其他网站运行却是正常的

而且我通过第三方连接数据库的工具可以正常连接到被挂网站的数据库

通过以上情况可以排除以下原因:

  • mysql容器没有问题
  • 数据库端口和连接参数也没问题(已经检查过配置文件,没有被外部篡改过)
  • 网站程序正常运行

这种情况下该如何处理呢? 当然是找日志了

第一步:查看主程序日志,没问题

第二步:查看mysql容器日志,发现问题

1
docker logs --tail=50 mysql

Table './wordpress_wai/wp_options' is marked as crashed and should be repaired when using LOCK TABLES

数据库没有问题,但是表有问题

解决方案

对表进行修复即可:

首先登录mysql选择指定的数据库,然后执行以下命令:

  1. 执行修复指令

    1
    repair table wp_option
  2. 检查表的状态

    1
    check table wp_option

修复前最好先备份数据库

1
mysqldump -uroot -p密码 数据库名 >xxxxx.sql

如果表损坏比较严重,可能无法备份数据库

如果你不知道如何查看mysql日志,那么直接运行备份数据库指令,也能帮你检查数据库是否存在问题

修复完成后无需重启mysql容器, 直接刷新网址即可正常访问

2021年9月1日补充

突然数据库又崩了, 网站同样提示error establishing a database connection

我查看docker日志 报如下错误:

1
Database page corruption on disk or a failed file read of page [page id: space=0, page number=5]. You may have to recover from a backup

此时mysql容器已经进不去了, 百度了一下说是数据库受损 要在my.cnf配置文件中添加innodb_force_recovery=1

可是我在conf目录下并没有找到my.cnf文件 不知道是被谁给删了 难道被入侵了

只好新建一个配置文件看看可不可行

1
vim my.cnf

然后将以下内容拷贝进去:

1
2
3
4
5
6
7
8
9
10
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# Custom config should go here
!includedir /etc/mysql/conf.d/

wq保存退出 然后重启mysql容器, 重新访问网站 还是不行

紧接着我在配置文件末尾添加了innodb_force_recovery=1

1
2
3
4
5
6
7
8
9
10
11
12
13
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
datadir = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# Custom config should go here
!includedir /etc/mysql/conf.d/


innodb_force_recovery=1

保存重启后, 网站正常访问, 问题解决

但是mysql容器日志一直提示:

1
[ERROR] [MY-012803] [InnoDB] innodb_force_recovery is on. We do not allow database modifications by the user. Shut down mysqld and edit my.cnf to set innodb_force_recovery=0

于是我把innodb_force_recovery值设为0 网站没问题 暂且就这样

关于innodb_force_recovery参数

  • Mode 1当遇到损坏页时,不使 MySQL 崩溃
  • Mode 2不运行后台操作
  • Mode 3不会尝试回滚事务
  • Mode 4不计算统计数据或应用存储/缓冲的变化
  • Mode 5在启动过程中不查看撤消日志
  • Mode 6在启动时不从重做日志(ib_logfiles)前滚

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

GCC调试工具GDB的常用指令

发表于 2021-01-20

常用指令

  1. 进入调试模式

    1
    gdb 可执行文件
  2. 如果忘了指定调试文件可以使用file指令指定

    1
    (gdb) file 文件名
  3. 使用quit指令退出调试模式 可简写为q

    1
    (gdb) q
  4. 使用start指令开始调试 停在第一行代码处

    1
    (gdb) start
  5. 使用step指令进行单步执行 可简写为s

    1
    (gdb) s   #会进入函数内部
  6. 使用next执行进行单步执行 可简写为n

    1
    (gdb) n  #不会进入函数内部
  7. 汇编级别单步执行(上面n和s为c语言级别单步指令)

    1
    2
    (gdb) ni #不进入函数内部
    (gdb) si #会进入函数内部
  8. 使用list指令列出所有源代码 可简写为l

    1
    (gdb) l
  9. 使用break指令设置断点位置 可简写为b

    1
    2
    3
    4
    5
    (gdb) b main #在main函数处打断点
    (gdb) b 10 #在第十行位置打断点
    (gdb) b test:10 #在test文件的第十行位置打断点
    (gdb) b 0x3400a #在0x3400a内存位置打断点
    (gdb) b 10 if i==3 #设置条件断点 i等于3时在第十行位置打断点 适用于循环
  10. 使用delete+断点编号指令删除断点 可简写为d

    1
    (gdb) delete 3 #删除编号为3的断点  清除时GDB不会给出任何提示
  11. 使用 clear+断点行号指令清除断点

    1
    (gdb) clear 3 #清除第三行的断点  清除时GDB会给出提示
  12. 使用 disable/enable + 断点编号 指令冻结或启动断点

    1
    disable 3,4 #冻结编号为3和4的断点 多个断点使用逗号分隔
  13. 使用info break指令查看断点的情况

    1
    (gdb) info break
  14. 使用 tbreak 指令设置临时断点

    1
    (gdb) tbreak 行号/函数名 #设置临时断点,到达后被自动删除
  15. 使用 awatch/watch + 变量 设置变量读写观察点

    1
    2
    (gdb) awatch/watch a #当变量a被读出或写入时程序被暂停 
    (gdb) rwatch a #当变量a被读出时程序被暂停
  16. 使用continue指令运行到断点处 可简写为c

    1
    (gdb) c
  17. 使用print指令打印变量的值 可简写为p

    1
    (gdb) p a #打印变量a的值
  18. 使用x指令打印指定内存地址数据

    1
    (gdb) x /6cb 0x804835c #打印地址0x804835c起始的内存内容,连续6个字节,以字符格式输出。
  19. 使用run指令运行整个程序 可简写为r

    1
    (gdb) r  #如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处
  20. 使用 call 指令直接运行某个函数

    1
    (gdb) call fun #在当前位置执行函数fun
  21. 使用display 指令设置需要跟踪的变量

    1
    (gdb) display a #跟踪变量a 每次断点到该处就显示该变量的值
  22. 使用 info display 显示当前所有跟踪的情况

    1
    (gdb) info display
  23. 使用undisplay+编号 指令取消对变量的跟踪

    1
    (gdb) undisplay 3 #取消对编号为3的跟踪事件
  24. 使用 set+ 变量 指令改变变量的值

    1
    (gdb) set i=3 #临时设置变量i的值为3
  25. 使用 set 指令设置运行时参数

    1
    (gdb) set i=3 #临时这只变量i的值为3
  26. 使用 show 指令查看运行时参数

    1
    (gdb) show i
  27. 使用 finish 指令函数结束

    1
    (gdb) finish
  28. 使用help指令查看指令使用说明

    1
    2
    (gdb) help print #查看print指令的解释说明
    (gdb) help #查看所有指令
  29. 使用info reg指令查看寄存器状态

    1
    (gdb)  info reg
  30. 使用 info stack指令查看堆栈状态

    1
    (gdb) info stack
  31. 运行shell指令

    1
    (gdb) shell ls   #运行shell指令ls。
  32. 其他指令

    1
    2
    3
    4
    5
    6
    7
    (gdb)  path #可设定程序的运行路径。 
    (gdb) show paths #查看程序的运行路径。


    (gdb)  cd   #相当于shell的cd命令。

    (gdb)  pwd  #显示当前的所在目录
  1. 使用回车重复上一条指令

本文为作者原创 转载时请注明出处 谢谢

img

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

视频教程录制计划

发表于 2021-01-17

技术视频

  1. 《Android进阶之逆向安全反编译视频教程-胖薯出品》

    • 录制时间 2020年11月6日
    • 部分视频观看:点击跳转
  2. 《Smali语言从入门到精通视频教程-胖薯出品》

    • 录制时间 2020年11月6日
    • 部分视频观看:点击跳转
  3. 《程序员进阶之三大架构汇编语言入门视频教程-胖薯出品》

    • 录制时间 2020年12月14日
    • 部分视频观看:点击跳转
  4. 《ARM汇编进阶之ARM64汇编视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  5. 《MIPS汇编进阶之MIPS64汇编视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  6. 《X86汇编进阶之Win32汇编视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  7. 《X86汇编进阶之Win64汇编视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  8. 《lua语言从入门到实战视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  9. 《硬件开发入门视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  10. 《从0到1打造一门属于自己的编程语言视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  11. 《从0到1开发一款操作系统视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  12. 《音乐制作之视唱练耳视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  13. 《虚幻游戏开发从0到1视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  14. 《音频插件开发视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  15. 《SO库的反编译视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:
  16. 《360和腾讯加固的原理和脱壳视频教程-胖薯出品》

    • 录制时间
    • 部分视频观看:

大家好 我已入驻面包多, 后续的付费教程会在上面发布 感谢大家的支持, 主页地址 : https://mbd.pub/o/newban/work

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

从0到1打造一门属于自己的编程语言(一)

发表于 2021-01-17

前言

学习编程语言的开发,目的不是为了造轮子,而是为了了解程序语言的本质和原理,方便我们日常的开发

学习此课程前需要提前掌握以下知识:

  • 了解汇编语言
  • 熟悉至少一门高级编程语言

编程语言的来源

我们如果想要和外国人交流,那么我们必须学会外语, 或者让外国人学咱们的语言

我们如果想要指挥计算机,那么我们必须学会计算机语言,让计算机学咱们的语言不太可能,至少现在不行!

很多人都认为我们平常使用的编程语言比如C语言 Java语言等就是计算机语言,这种说法不太严谨, 因为计算机压根不认识编程语言,它只认识二进制码, 也就是说 二进制码才是计算机真正的语言

那我们要指挥计算机岂不是得学二进制码(机器码),在编程语言发明之前,确实是如此

科技的进步来源于懒惰

人类势必不会甘愿长期忍受机器码的摧残, 为了摆脱效率低下的编码,于是乎,聪明的人类发明了编程语言,比如汇编, 相比机器码汇编显然要舒服的多, 但是随着时间的推移,人们发现汇编语言存在非常严重的弊端, 最突出的一点就是不同cpu架构需要制定一套不同指令集,通俗一点就是不同cpu对应着不同的一套汇编语言,这就导致了无法跨平台

有人会问,为什么当时大家不使用同一种cpu呢, 历史不能预知未来的发展,每个时代都有各自的商业竞争

新技术的出现往往是因为问题的长期累积

于是乎,跨平台语言C语言问世了, 但是C语言知识语言跨平台,但是其编写的程序并不跨平台

于是乎,可以程序跨平台的Java语言问世了

……..

从这段历史,我们不难发现:

编程语言只是一个方便人类与计算机交流的工具

只是工具,仅此而已

我们现在花大量时间和精力所学所用的都是别人制作出来的工具

当我们因熟练掌握几门编程语言而洋洋得意时,是否有想过,我们只是一个工具的熟练运用者

我并不是说学语言很low, 毕竟编程语言的门槛也不低,需要花大量时间和精力才能有效掌握,我只是想说,一旦你明白了语言的创造过程, 那就等于你掌握了现在市面上所有的编程语言, 所有的语言,原理都是一样的,只不过语法和关键字不同,仅此而已

也就是说,我们需要去了解工具的生产过程

思考

如果你去网上搜相关编程语言制作的视频或资料, 基本上都是词法分析,语法分析,语义分析等等, 让人一头雾水, 直接劝退

试想一下,在若干年前编程语言还没有问世的时候,有词法语法语义符号token等等这一些个含义么? 完全没有!

这些理论都是前人经验总结而成, 经验固然很好,能少走弯路,但是对于初学者来讲极其不友好

只有从初学者的角度出发,才能更平滑地学习到原本复杂的知识

因此抛开这些专业术语吧,从0开始出发

起步

假如现在编程语言还未问世,你现在要自创一门语言方便人类开发, 你会怎么做?

比如我想让计算机帮忙算个数,计算1+1

原本使用机器码可能得这样写:

1
4F 9B 55 7C 2D 3A  ;实际过程中我们一般使用十六进制进行表示,cpu执行的时候执行的是对应的二进制

此时,我可能会考虑用一句话来代替这个计算1加1的功能,比如

1
加:1+1   ;这是不是好理解多了

问题来了, 如果将我这句话转成机器码呢? 也就是说,我们需要将这句话翻译成机器码, 那怎么翻译呢? 是不是得需要一个翻译工具呀

于是乎,我们与此同时需要想办法整一个翻译工具, 由于我设计的这句话是敲在计算机上的,而不是写在纸上的, 如果是写在纸上的,兴许我们可以造一台机器将我写的内容转印成机器码,然后机器码敲入计算机:cry:… 这种愚蠢的做法, 简直就是科技的倒退

既然是直接敲在计算机中,那我们的翻译工具必然也是一个能被cpu执行的程序, 那我们需要先编写翻译工具这个程序的机器码

理论上是这么个逻辑

我们需要一边指定语法规则,一边编写和优化的翻译程序,因为我们的需求不单单是让计算机做加法运算

这个能把我们指定的语言翻译成机器码的翻译工具,就是当今所说的编译器,后文皆以编译器替代

编译器该如何写

由于源代码都是存放在文件中,按照我们的正常思维,最先想到的是将这个文件中的内容读取出来,然后从头到尾进行匹配判断,根据不同的关键字判断不同的功能,然后用与之对应的机器码进行替换

cpu在进行文件读取的时候,本质上读取的是二进制,那我们编写的中文或者英文和二进制数据的一一对应关系就涉及到编码格式问题,常见的编码格式有:

  • ASCII码 (只识别英文)
  • GBK (识别英文和中文)
  • UTF-8 (识别各个国家的语言)
  • …

假如我们接下来要使用UTF-8进行编码,那么我们需要指定一张表,也就是二进制码和功能之间的一一对应关系,比如算术运算中加这个关键字:编译器从文本中连续读取两个字节二进制数据然后查表,如果对应上了加法功能,那么继续往后读取需要进行运算的内容,读到结束标记的时候,然后将之前所读取的二进制转化成与之对应功能的机器码,以此类推,这个结束标记也是由我们来定,我们可以使用分号、回车换行或者其它特殊的符号作为一行语句的结束

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

硬件开发之个人PCB电路板制作

发表于 2021-01-07

流程

第一步 画电路原理图

  1. 工具

    Altium Designer 19: 中文官网:https://www.altium.com.cn/products/downloads

第二步 联系PCB厂家

  1. 廉价厂家推荐
    • 嘉立创 :10x10cm的板子5张 只需5块钱
    • 捷配 :10x10cm的板子5张 19块钱

第三步 电子元器件采购

第四步 电子元器件焊接

第四步 电路板测试

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

硬件开发之基础知识(-)

发表于 2021-01-06

前言

随着智能家居的兴起,5G时代的到来, 智能硬件扮演者越来越关键的角色, 对于老百姓的我们而言,占据先机最好的办法的就是了解并掌握它, 因为知识是公平的

基础物理知识

这些我们在学生时代都学过,现在需要把它们都重新拾起来

1. 电压

可以理解为电子移动的动力,压力即是动力,单位:V

2. 电流

电荷的定向流动 ,犹如水流

流动的电才能将电灯点亮

单位:A

3.电的产生

产生电的方式有很多种,摩擦生电,电解质生电,一般我们日常使用的电,是通过发电机发电,它的原理是:

闭合电路的一部分导体在磁场里做切割磁感线的运动时,导体中就会产生电流

材料:

1. 磁铁
 2. 线圈

自制发电机:https://v.163.com/static/1/VYUIDVSRG.html

电子元器件

分类:

  • 元件:工厂在加工时没改变原材料分子成分的产品可称为元件。元件属于不需要能源的器件。它包括:电阻、电容、电感等
  • 器件:工厂在生产加工时改变了原材料分子结构的产品称为器件。器件需要消耗能源,它包括双极性晶体三极管 场效应晶体管 可控硅 等

常见电子元器件

  1. 电阻
  2. 电容
  3. 二极管
  4. 三极管
  5. 继电器
  6. 电容器
  7. 电位器
  8. 传感器

电流的的流向判断

第一步:判断是否有一条电路直接将正负极向连,如果有则短路,没有则进入第二步

第二步:在电流分叉路口,判断是否有一条电路没有连接任何元器件,如果有则走这条路,其他路不通, 如果都连接了器件,那么都有电流通过

串联和并联电路

1.串联电路的特点:
(1)电流:文字表达:串联电路中各处电流都相等.
公式表达:I=I1=I2=I3=……=In
(2)电压:文字表达:串联电路中的总电压等于各部分电路电压之和.
公式表达:U=U1+U2+U3+……+Un
(3)电阻:文字表达:串联电路中的总电阻等于各部分电路的电阻之和.
公式表达:R=R1+R2+R3+……+Rn
(4)分压定律:文字表达:串联电路中各部分电路两端电压与其电阻成正比.
公式表达:U1/R1=U2/R2=U3/R3=.=Un/Rn
另种表达:U1:U2:U3:…:Un= R1:R2:R3:…:Rn
特例:U1/U2=R1/R2
2.并联电路的特点:
(1)电流:文字表达:并联电路中总电流等于各支路中的电流之和.
公式表达:I=I1+I2+I3+……+In
(2)电压:文字表达:并联电路中各支路两端的电压都相等.
公式表达:U=U1=U2=U3=……=Un
(3)电阻:文字表达:并联电路总电阻的倒数等于各支路电阻倒数之和.
公式表达:1/R=1/R1+1/R2+1/R3+……+1/Rn
(4)分流定律:文字表达:并联电路中,流过各支路的电流与其电阻成反比.
公式表达:I1R1=I2R2=I3R3= …=InRn
特例:I1/I2=R2/R1

总结

在串联电路中

  • 电阻越大,截取的电压越大

在并联电路中

  • 电阻越大, 截取的电流越小
  • 分支电路越多,总电流越大

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

关于字节和字长以及半字的关系

发表于 2021-01-05

关于字节

一个字节是固定为8个二进制位

关于字(word)

字的长度是可变的,它和cpu一次性能操作的实际位数有关

比如16位的cpu一次能操作16位数,因次2个字节代表一个字

如果是32位cpu,那么32位也就是4个字节代表一个字的长度(word)

关于半字

半字即为字长的一半,在16位cpu中,半字即为一个字节,故在16位中没有半字这个说法,一半32位以上cpu环境中常用

本文为作者原创 转载时请注明出处 谢谢

乱码三千 – 点滴积累 ,欢迎来到乱码三千技术博客站

1…272829…50

乱码三千

android程序员一枚,擅长java,kotlin,python,金融投资,欢迎交流~

491 日志
143 标签
RSS
© 2025 乱码三千
本站总访问量次
由 Hexo 强力驱动
|
主题 — NexT.Muse v5.1.4
0%