可以参考 : http://blog.csdn.net/bluesummerg/article/details/5940452   (强大的反汇编)
http://www.cnblogs.com/yanhc/archive/2011/09/13/2175280.html // 本文学习目标:
  1. 微观上,对此start.S的每一行,都有了基本的了解
  2. 宏观上,对基于ARM核的S3C24X0的CPU的启动过程,有更加清楚的概念

注意:

————————————————————————————————————————————————————————————————————————————

@ARM体系结构规定在上电复位后的起始位置,必须有8条连续的跳            

@转指令,通过硬件实现。他们就是异常向量表。                   

也就是                                      



#include <config.h>
#include <version.h> /*
*************************************************************************
*
* Jump vector table as in table . in []
*
*************************************************************************
*/ 1、设置中断向量表: .globl _start // 就是相当于C语言中的Extern,声明此变量,并且告诉链接器此变量是全局的,外部可以访问,所以外部的/home/dennis/Desktop/uboot1020/u-boot-1.1.6/board/my2440/u-boot.lds 中用到此变量
_start: b reset // 表示其是一个标号Label , 而同时,_start的值,也就是这个代码的位置了,此处即为代码的最开始,相对的0的位置 , b reset // 就是跳转到对应的标号为reset的位置(复位向量)
                       // 如果是从NorFlash启动,那么其地址是0,如果是重新relocate代码之后,就是我们定义的值了,即,在/home/dennis/Desktop/uboot1020/u-boot-1.1.6/board/my2440/config.mk 中
                        
下面便是
home/dennis/Desktop/uboot1020/u-boot-1.1.6/board/my2440/config.mk  中的代码。

也就是   _start=TEXT_BASE=0x33F80000、

网上讲解: _start是整个u-boot程序的入口点,即链接后,该处是整个程序的第一条指令。如果从flash启动,就是0x0,如果从SDRAM中这姓,则是TEXT_BASE=0x33F80000。
程序的入口点是由链接脚本所指定,脚本文件位于board\my2440\u-boot.lds。在该脚本文件中:ENTRY(_start) 即指定程序的入口地址。


 #
# SMDK2410 has bank of MB DRAM
#
# '0000 to 3400'
#
# Linux-Kernel is expected to be at '8000, entry 3000'
# optionally with a ramdisk at '
#
# we load ourself to 33F8'
#
# download area is '
# TEXT_BASE = 0x33F80000

LDR{条件} 目的寄存器,<存储器地址>   LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取32位的字数据到通用寄存器,然后对数据进行处理。当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转
ARM是RISC结构,数据从内存到CPU之间的移动只能通过L/S指令来完成,也就是ldr/str指令 ,
ldr pc, _undefined_instruction // /*未定义指令异常,0x04*/ :ldr pc, _undefined_instruction。他把_undefined_instruction标号处(即地址33f80020)的值(即33f80140)放入pc指针,就是跳转到相应的中断处理函数的地址处
ldr pc, _software_interrupt        // /*软中断异常,0x08*/
ldr pc, _prefetch_abort          ///*内存操作异常,0x0c*/
ldr pc, _data_abort            // /*数据异常,0x10*/
ldr pc, _not_used             // /*未适用,0x14*/
ldr pc, _irq                // /*慢速中断异常,0x18*/
ldr pc, _fiq                // /*快速中断异常,0x1c*/

// 那么问题来了: 第一个为什么 用 b reset 呢,应为 reset用b,就是因为reset在MMU建立前后都有可能发生
@其他的异常只有在MMU建立之后才会发生

_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq .balignl ,0xdeadbeef // 接下来的代码,都要16字节对齐,不足之处,用0xdeadbeef填充 我们来解释:
_undefined_instruction:    .word undefined_instruction  
对应反汇编:
33f80020:    33f80140     mvnccs    r0, #16    ; 0x10         // 33f80020地址处存放的是undefined_instruction,函数位置在33f80140

等于说:

_rWTCON:

.word 0x15300000

就是在当前地址,即_rWTCON处放一个值0x15300000

翻译成intel的汇编语句就是:

_rWTCON dw 0x15300000

以上内容 对应的反汇编源码:

====================================================================================================——————————————————————————————————————————————————————————————————————————————————————————————————————
33f80000 <_start>:
33f80000:    ea000012     b    33f80050 <start_code>
33f80004:    e59ff014     ldr    pc, [pc, #20]    ; 33f80020 <_undefined_instruction>
33f80008:    e59ff014     ldr    pc, [pc, #20]    ; 33f80024 <_software_interrupt>
33f8000c:    e59ff014     ldr    pc, [pc, #20]    ; 33f80028 <_prefetch_abort>
33f80010:    e59ff014     ldr    pc, [pc, #20]    ; 33f8002c <_data_abort>
33f80014:    e59ff014     ldr    pc, [pc, #20]    ; 33f80030 <_not_used>
33f80018:    e59ff014     ldr    pc, [pc, #20]    ; 33f80034 <_irq>
33f8001c:    e59ff014     ldr    pc, [pc, #20]    ; 33f80038 <_fiq> 33f80020 <_undefined_instruction>:
33f80020:    33f80140     mvnccs    r0, #16    ; 0x10 33f80024 <_software_interrupt>:
33f80024:    33f801a0     mvnccs    r0, #40    ; 0x28 33f80028 <_prefetch_abort>:
33f80028:    33f80200     mvnccs    r0, #0    ; 0x0 33f8002c <_data_abort>:
33f8002c:    33f80260     mvnccs    r0, #6    ; 0x6 33f80030 <_not_used>:
33f80030:    33f802c0     mvnccs    r0, #12    ; 0xc 33f80034 <_irq>:
33f80034:    33f80320     mvnccs    r0, #-2147483648    ; 0x80000000 33f80038 <_fiq>:
33f80038:    33f80380     mvnccs    r0, #2    ; 0x2 33f8003c:    deadbeef     cdple    14, 10, cr11, cr13, cr15, {7} // 接下来的代码,都要16字节对齐,不足之处,用0xdeadbeef填充 ===========================================================================================——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

3、保存变量的数据区,保存一些全局变量,用于BOOT程序从FLASH拷贝@到RAM,或者其它的使用。
还有一些变量的长度是通过连接脚本里得到,实际上由编译器算出

/*
*************************************************************************
*
* Startup Code (reset vector)
*
* do important init only if we don't start from memory!
* relocate armboot to ram
* setup stack
* jump to second stage
*
*************************************************************************
*/ _TEXT_BASE:
.word TEXT_BASE      // 因为linux开始地址是0x30000000,我这里是64M SDRAM,所以@TEXT_BASE = 0x33F80000 ,/*uboot映像在SDRAM中的重定位地址*/ .globl _armboot_start            //     
_armboot_start:
.word _start // 用_start来初始化_armboot_start 相当于C语言 : *(_armboot_start) = _start /*
* These are defined in the board-specific linker script. // 下面这些是定义在开发板目录链接脚本中的
*/
.globl _bss_start
_bss_start:
.word __bss_start // 关于_bss_start和_bss_end都只是两个标号,对应着此处的地址,而两个地址里面分别存放的值是__bss_start和_end,这两个的值,__bss_start定义在和开发板相关的u-boot.lds中,_bss_start保存的是__bss_start标号所在的地址 .globl _bss_end //
_bss_end:
.word _end // 这样赋值是因为代码所在地址非编译时的地址,直接取得该标号对应地址 中断的堆栈设置

#ifdef CONFIG_USE_IRQ
/* IRQ stack memory (calculated at run-time) */
.globl IRQ_STACK_START
IRQ_STACK_START:
.word 0x0badc0de /* IRQ stack memory (calculated at run-time) */
.globl FIQ_STACK_START
FIQ_STACK_START:
.word 0x0badc0de
#endif

同上,IRQ_STACK_START和FIQ_STACK_START,也是在cpu_init中用到了。


不过此处,是只有当定义了宏CONFIG_USE_IRQ的时候,才用到这两个变量,其含义也很明显,


只有用到了中断IRQ,才会用到中断的堆栈,才有中端堆栈的起始地址。


快速中断FIQ,同理。


2、 设置为 特权模式(管理模式)
********************************************************************************************************************************************************************************************************** @复位后执行程序
@真正的初始化从这里开始了。其实在CPU一上电以后就是跳到这里执行的
/*
* the actual reset code
*/ reset:
/*
* set the cpu to SVC32 mode
*/
mrs r0,cpsr // MRS指令用于将 程序状态寄存器(CPSR) 的内容传送到通用寄存器中
bic r0,r0,#0x1f // BIC{条件}{S} 目的寄存器,操作数1,操作数2 BIC指令用于清除操作数1的某些位,并把结果放置到目的寄存器中。操作数1应是一个寄存器
                  // = and r0 ,r0 ,#0xffffffE0 也就是把 r0 后5 位 清0 [4:0] ,那么就到了 用户模式
orr r0,r0,#0xd3 // 禁止IRQ,FIQ中断,并将处理器置于管理模式 (第 67 位置 1 ),至于 后五位 应该仍然为 0 把,应为是按位 或 运算啊 (好像理解也不对啊)


msr cpsr,r0 // 禁止IRQ,FIQ中断,并将处理器置于管理模式 执行结果: **********************************************************************************************************************************************************************************************************

@关闭看门狗定时器的自动复位功能并屏蔽所有中断,上电后看门狗为开,中断为关
/* turn off the watchdog */
#if defined(CONFIG_S3C2400)
# define pWTCON 0x15300000
# define INTMSK 0x14400008 /* Interupt-Controller base addresses */
# define CLKDIVN 0x14800014 /* clock divisor register */
#elif defined(CONFIG_S3C2410) // @关闭看门狗定时器的自动复位功能并屏蔽所有中断,上电后看门狗为开,中断为关
# define pWTCON 0x53000000 // pWTCON定义为看门狗控制寄存器的地址(s3c2410和s3c2440相同)
# define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ INTMSK定义为主中断屏蔽寄存器的地址(s3c2410和s3c2440相同)
# define INTSUBMSK 0x4A00001C @INTSUBMSK定义为副中断屏蔽寄存器的地址(s3c2410和s3c2440相同)
# define CLKDIVN 0x4C000014 /* clock divisor register */ @CLKDIVN定义为时钟分频控制寄存器的地址(s3c2410和s3c2440相同)
#endif @至此寄存器地址设置完毕 #if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410)
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0]
// r1寄存器的值,传送到地址值为r0的(存储器)内存中, 也就是C语言 *r0 = r1
对于S3C2440和S3C2410的WTCON寄存器的[0]控制允许或禁止看门狗定时器的复位输出功能,设置为“0”禁止复位功能。 ********************************************************************************************************************************************************************************************************

关闭中断

    /*
* mask all IRQs by setting all bits in the INTMR - default
*/
mov r1, #0xffffffff
ldr r0, =INTMSK
str r1, [r0] // 将INTMSK寄存器设置为0xffffffff,即,将所有的中端都mask了。 # if defined(CONFIG_S3C2410)
ldr r1, =0x3ff
ldr r0, =INTSUBMSK
str r1, [r0] 此处是将2410的INTSUBMSK设置为0x3ff。
# endif

@对于S3C2410的INTMSK寄存器的32位和INTSUBMSK寄存器的低11位每一位对应一个中断,相应位置“1”为不响应相应的中断。对于S3C2440的INTSUBMSK有15位可用,所以应该为0x7fff了。
/* FCLK:HCLK:PCLK = 1:2:4 */
/* default FCLK is 120 MHz ! */
ldr r0, =CLKDIVN
mov r1, #3
str r1, [r0] @时钟分频设置,FCLK为核心提供时钟,HCLK为AHB(ARM920T,内存@控制器,中断控制器,LCD控制器,DMA和主USB模块)提供时钟,@PCLK为APB(看门狗、IIS、I2C、PWM、MMC、ADC、UART、GPIO、@RTC、SPI)提供时钟。分频数一般选择1:4:8,所以HDIVN=2,PDIVN=1,@CLKDIVN=5,这里仅仅是配置了分频寄存器,关于MPLLCON的配置肯@定写在lowlevel_init.S中了
@归纳出CLKDIVN的值跟分频的关系:
@0x0 = 1:1:1  ,  0x1 = 1:1:2 , 0x2 = 1:2:2  ,  0x3 = 1:2:4,  0x4 = 1:4:4,  0x5 = 1:4:8, 0x6 = 1:3:3, 
0x7 = 1:3:6
@S3C2440的输出时钟计算式为:Mpll=(2*m*Fin)/(p*2^s)
S3C2410的输出时钟计算式为:Mpll=(m*Fin)/(p*2^s)
m=M(the value for divider M)+8;p=P(the value for divider P)+2
M,P,S的选择根据datasheet中PLL VALUE SELECTION TABLE表格进行,
 
我的开发板晶振为16.9344M,所以输出频率选为:399.65M的话M=0x6e,P=3,S=1
@s3c2440增加了摄像头,其FCLK、HCLK、PCLK的分频数还受到CAMDIVN[9](默认为0),CAMDIVN[8](默认为0)的影响

#endif /* CONFIG_S3C2400 || CONFIG_S3C2410 */

*************************************************************************************************************************************************************************************************************


@选择是否初始化CPU
/* * we do sys-critical inits only at reboot, * not when booting from ram! */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT bl cpu_init_crit 执行CPU初始化,BL完成跳转的同时会把后面紧跟的一条指令地址保存到连接寄存器LR(R14)中。以使子程序执行完后正常返回。 #endif 

@调试阶段的代码是直接在RAM中运行的,而最后需要把这些代码 @固化到Flash中,因此U-Boot需要自己从Flash转移到
@RAM中运行,这也是重定向的目的所在。
@通过adr指令得到当前代码的地址信息:如果U-boot是从RAM @开始运行,则从adr,r0,_start得到的地址信息为
@r0=_start=_TEXT_BASE=TEXT_BASE=0x33F80000; @如果U-bootFlash开始运行,即从处理器对应的地址运行,
@r0=0x0000,这时将会执行copy_loop标识的那段代码了。
@ _TEXT_BASE 定义在board/smdk2410/config.mk

#ifndef CONFIG_SKIP_RELOCATE_UBOOT
relocate: /* relocate U-Boot to RAM */
adr r0, _start /* r0 <- current position of code */
ldr r1, _TEXT_BASE /* test if we run from flash or RAM */
cmp r0, r1 /* don't reloc during debug */
beq stack_setup ldr r2, _armboot_start
ldr r3, _bss_start
sub r2, r3, r2 /* r2 <- size of armboot */
add r2, r0, r2 /* r2 <- source end address */ copy_loop:
ldmia r0!, {r3-r10} /* copy from source address [r0] */
stmia r1!, {r3-r10} /* copy to target address [r1] */
cmp r0, r2 /* until source end addreee [r2] */
ble copy_loop
#endif /* CONFIG_SKIP_RELOCATE_UBOOT */ /* Set up the stack */ 初始化堆栈
stack_setup:
ldr r0, _TEXT_BASE /* upper KiB: relocated uboot */
sub r0, r0, #CFG_MALLOC_LEN /* malloc area */
sub r0, r0, #CFG_GBL_DATA_SIZE /* bdinfo */
#ifdef CONFIG_USE_IRQ
sub r0, r0, #(CONFIG_STACKSIZE_IRQ+CONFIG_STACKSIZE_FIQ)
#endif
sub sp, r0, # /* leave words for abort-stack */ clear_bss:
ldr r0, _bss_start /* find start of bss segment */
ldr r1, _bss_end /* stop here */
mov r2, #0x00000000 /* clear */ clbss_l:str r2, [r0] /* clear loop... */
add r0, r0, #
cmp r0, r1
ble clbss_l #if
/* try doing this stuff after the relocation */
ldr r0, =pWTCON
mov r1, #0x0
str r1, [r0] /*
* mask all IRQs by setting all bits in the INTMR - default
*/
mov r1, #0xffffffff
ldr r0, =INTMR
str r1, [r0] /* FCLK:HCLK:PCLK = :: */
/* default FCLK is MHz ! */
ldr r0, =CLKDIVN
mov r1, #
str r1, [r0]
/* END stuff after relocation */
#endif ldr pc, _start_armboot _start_armboot: .word start_armboot /*
*************************************************************************
*
* CPU_init_critical registers
*
* setup important registers
* setup memory timing
*
*************************************************************************
*/ @CPU初始化 ************************************************************************************************************************************************************************************
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
cpu_init_crit:
/*
* flush v4 I/D caches
*/
mov r0, #
mcr p15, , r0, c7, c7, /* flush v3/v4 cache */
mcr p15, , r0, c8, c7, /* flush v4 TLB */ /*
* disable MMU stuff and caches
*/
mrc p15, , r0, c1, c0,
bic r0, r0, #0x00002300 @ clear bits , : (--V- --RS)
bic r0, r0, #0x00000087 @ clear bits , : (B--- -CAM)
orr r0, r0, #0x00000002 @ set bit (A) Align
orr r0, r0, #0x00001000 @ set bit (I) I-Cache
mcr p15, , r0, c1, c0, /*
* before relocating, we have to setup RAM timing
* because memory timing is board-dependend, you will
* find a lowlevel_init.S in your board directory.
*/
mov ip, lr
bl lowlevel_init
mov lr, ip
mov pc, lr
#endif /* CONFIG_SKIP_LOWLEVEL_INIT */ /*
*************************************************************************
*
* Interrupt handling
*
*************************************************************************
*/ @
@ IRQ stack frame.
@
#define S_FRAME_SIZE #define S_OLD_R0
#define S_PSR
#define S_PC
#define S_LR
#define S_SP #define S_IP
#define S_FP
#define S_R10
#define S_R9
#define S_R8
#define S_R7
#define S_R6
#define S_R5
#define S_R4
#define S_R3
#define S_R2
#define S_R1
#define S_R0 #define MODE_SVC 0x13
#define I_BIT 0x80 /*
* use bad_save_user_regs for abort/prefetch/undef/swi ...
* use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
*/ .macro bad_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
ldr r2, _armboot_start
sub r2, r2, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r2, r2, #(CFG_GBL_DATA_SIZE+) @ set base words into abort stack
ldmia r2, {r2 - r3} @ get pc, cpsr
add r0, sp, #S_FRAME_SIZE @ restore sp_SVC add r5, sp, #S_SP
mov r1, lr
stmia r5, {r0 - r3} @ save sp_SVC, lr_SVC, pc, cpsr
mov r0, sp
.endm .macro irq_save_user_regs
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0-r12
add r8, sp, #S_PC
stmdb r8, {sp, lr}^ @ Calling SP, LR
str lr, [r8, #] @ Save calling PC
mrs r6, spsr
str r6, [r8, #] @ Save CPSR
str r0, [r8, #] @ Save OLD_R0
mov r0, sp
.endm .macro irq_restore_user_regs
ldmia sp, {r0 - lr}^ @ Calling r0 - lr
mov r0, r0
ldr lr, [sp, #S_PC] @ Get PC
add sp, sp, #S_FRAME_SIZE
subs pc, lr, # @ return & move spsr_svc into cpsr
.endm .macro get_bad_stack
ldr r13, _armboot_start @ setup our mode stack
sub r13, r13, #(CONFIG_STACKSIZE+CFG_MALLOC_LEN)
sub r13, r13, #(CFG_GBL_DATA_SIZE+) @ reserved a couple spots in abort stack str lr, [r13] @ save caller lr / spsr
mrs lr, spsr
str lr, [r13, #] mov r13, #MODE_SVC @ prepare SVC-Mode
@ msr spsr_c, r13
msr spsr, r13
mov lr, pc
movs pc, lr
.endm .macro get_irq_stack @ setup IRQ stack
ldr sp, IRQ_STACK_START
.endm .macro get_fiq_stack @ setup FIQ stack
ldr sp, FIQ_STACK_START
.endm /*
* exception handlers @异常向量处理
@每一个异常向量处其实只放了一条跳转指令(因为每个异常向量只 @有4个字节不能放太多的程序),跳到相应的异常处理程序中。

*/
.align
undefined_instruction:
get_bad_stack
bad_save_user_regs
bl do_undefined_instruction .align
software_interrupt:
get_bad_stack
bad_save_user_regs
bl do_software_interrupt .align
prefetch_abort:
get_bad_stack
bad_save_user_regs
bl do_prefetch_abort .align
data_abort:
get_bad_stack
bad_save_user_regs
bl do_data_abort .align
not_used:
get_bad_stack
bad_save_user_regs
bl do_not_used #ifdef CONFIG_USE_IRQ .align
irq:
get_irq_stack
irq_save_user_regs
bl do_irq
irq_restore_user_regs .align
fiq:
get_fiq_stack
/* someone ought to write a more effiction fiq_save_user_regs */
irq_save_user_regs
bl do_fiq
irq_restore_user_regs #else .align
irq:
get_bad_stack
bad_save_user_regs
bl do_irq .align
fiq:
get_bad_stack
bad_save_user_regs
bl do_fiq #endif 可知start.S的流程为:异常向量——上电复位后进入复位异常向量——跳到启动代码处——设置处理器进入管理模式——关闭看门狗——关闭中断——设置时钟分频——关闭MMU和CACHE——进入lowlever_init.S——检查当前代码所处的位置,如果在FLASH中就将代码搬移到RAM中

start.s 解析(一)的更多相关文章

  1. 【原】Android热更新开源项目Tinker源码解析系列之三:so热更新

    本系列将从以下三个方面对Tinker进行源码解析: Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Android热更新开源项目Tinker源码解析系列之二:资源文件热更新 A ...

  2. .NET Core中的认证管理解析

    .NET Core中的认证管理解析 0x00 问题来源 在新建.NET Core的Web项目时选择“使用个人用户账户”就可以创建一个带有用户和权限管理的项目,已经准备好了用户注册.登录等很多页面,也可 ...

  3. Html Agility Pack 解析Html

    Hello 好久不见 哈哈,今天给大家分享一个解析Html的类库 Html Agility Pack.这个适用于想获取某网页里面的部分内容.今天就拿我的Csdn的博客列表来举例. 打开页面  用Fir ...

  4. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  5. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  6. 多线程爬坑之路-Thread和Runable源码解析之基本方法的运用实例

    前面的文章:多线程爬坑之路-学习多线程需要来了解哪些东西?(concurrent并发包的数据结构和线程池,Locks锁,Atomic原子类) 多线程爬坑之路-Thread和Runable源码解析 前面 ...

  7. Asp.Net WebApi核心对象解析(下篇)

    在接着写Asp.Net WebApi核心对象解析(下篇)之前,还是一如既往的扯扯淡,元旦刚过,整个人还是处于晕的状态,一大早就来处理系统BUG,简直是坑爹(好在没让我元旦赶过来该BUG),队友挖的坑, ...

  8. 【知识必备】内存泄漏全解析,从此拒绝ANR,让OOM远离你的身边,跟内存泄漏say byebye

    一.写在前面 对于C++来说,内存泄漏就是new出来的对象没有delete,俗称野指针:而对于java来说,就是new出来的Object放在Heap上无法被GC回收:而这里就把我之前的一篇内存泄漏的总 ...

  9. SQL Server 数据加密功能解析

    SQL Server 数据加密功能解析 转载自: 腾云阁 https://www.qcloud.com/community/article/194 数据加密是数据库被破解.物理介质被盗.备份被窃取的最 ...

  10. .NetCore中的日志(1)日志组件解析

    .NetCore中的日志(1)日志组件解析 0x00 问题的产生 日志记录功能在开发中很常用,可以记录程序运行的细节,也可以记录用户的行为.在之前开发时我一般都是用自己写的小工具来记录日志,输出目标包 ...

随机推荐

  1. ASP.NET一些公共方法commTools

    using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Secu ...

  2. WCF TCP 错误代码 10061: 由于目标计算机积极拒绝

    表象是连不上服务端,本质原因多种多样,网络硬件问题导致的网络不通.服务本身问题或没有启动.或者防火墙阻隔等等不一而足. 1.ping看服务端能否ping通: 2.telnet ip地址 端口 ,看看是 ...

  3. The Beginner’s Guide to iptables, the Linux Firewall

    Iptables is an extremely flexible firewall utility built for Linux operating systems. Whether you’re ...

  4. 关于使用UDP(TCP)跨局域网,NAT穿透的心得

    前言:        最近我用java做了一个C/S的类似QQ之类的IM系统(即时通讯系统),遇到了不能跨局域网通讯的问题,经过在网上,和书上查阅了一些资料,了解了一些情况,现在就总结一下我的解决方案 ...

  5. 【C++】error C4146: 一元负运算符应用于无符号类型,结果仍为无符号类型

    刷leetcode 263.uglynumber时,代码如下: class Solution { public: bool isUgly(int num) { int temp = num; ) re ...

  6. Tea---hdu5881(规律)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5881 题意: 现在有一壶水,体积在[L, R]范围内,现有两个空杯子,现想要把这壶水倒入这两个杯子中去 ...

  7. jQuery动态对表格Table进行添加或删除行以及修改列值操作

    jQuery,不仅可以以少量的代码做很多操作,而且兼容性好(各种浏览器,各种版本). 下面用jQuery动态对表格Table进行添加或删除行以及修改列值操作 1.jQuery代码 <script ...

  8. java发展道路

    1.

  9. Redis实现分布式锁

    http://redis.io/topics/distlock 在不同进程需要互斥地访问共享资源时,分布式锁是一种非常有用的技术手段. 有很多三方库和文章描述如何用Redis实现一个分布式锁管理器,但 ...

  10. webApi中参数传递

    webApi中参数传递 一:无参数的get方法: 前端:    function GetNoParam() { //为了统一:我们都采用$.ajax({}) 方法; $.ajax({ url: '/a ...